public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Ni, Ray" <ray.ni@intel.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>,
	"Wu, Hao A" <hao.a.wu@intel.com>
Cc: "Dong, Eric" <eric.dong@intel.com>,
	"Wang, Jian J" <jian.j.wang@intel.com>
Subject: Re: [edk2-devel] [PATCH v3 2/2] MdeModulePkg/AhciPei: Add PEI BlockIO support
Date: Tue, 23 Apr 2019 18:14:57 +0000	[thread overview]
Message-ID: <734D49CCEBEEF84792F5B80ED585239D5C0FEB4D@SHSMSX104.ccr.corp.intel.com> (raw)
In-Reply-To: <20190423080630.14992-3-hao.a.wu@intel.com>

Reviewed-by: Ray Ni <ray.ni@intel.com>

> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> Wu, Hao A
> Sent: Tuesday, April 23, 2019 1:07 AM
> To: devel@edk2.groups.io
> Cc: Wu, Hao A <hao.a.wu@intel.com>; Ni, Ray <ray.ni@intel.com>; Dong,
> Eric <eric.dong@intel.com>; Wang, Jian J <jian.j.wang@intel.com>
> Subject: [edk2-devel] [PATCH v3 2/2] MdeModulePkg/AhciPei: Add PEI
> BlockIO support
> 
> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1483
> 
> This commit will add the PEI BlockIO (2) PPIs support for AHCI mode ATA
> devices.
> 
> More specifically, the driver will consume the ATA AHCI host controller
> PPI for ATA controllers working under AHCI code within the system. And
> then produces the below additional PPIs for each controller:
> 
> EFI PEI Recovery Block IO PPI
> EFI PEI Recovery Block IO2 PPI
> 
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Signed-off-by: Hao Wu <hao.a.wu@intel.com>
> ---
>  MdeModulePkg/Bus/Ata/AhciPei/AhciPei.inf      |   4 +
>  MdeModulePkg/Bus/Ata/AhciPei/AhciPei.h        |  30 ++
>  MdeModulePkg/Bus/Ata/AhciPei/AhciPeiBlockIo.h | 257 ++++++++++
>  MdeModulePkg/Bus/Ata/AhciPei/AhciMode.c       | 118 +++++
>  MdeModulePkg/Bus/Ata/AhciPei/AhciPei.c        |  35 ++
>  MdeModulePkg/Bus/Ata/AhciPei/AhciPeiBlockIo.c | 516
> ++++++++++++++++++++
>  6 files changed, 960 insertions(+)
> 
> diff --git a/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.inf
> b/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.inf
> index bf686a198f..912ff7a8ba 100644
> --- a/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.inf
> +++ b/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.inf
> @@ -26,6 +26,8 @@ [Defines]
>  [Sources]
>    AhciPei.c
>    AhciPei.h
> +  AhciPeiBlockIo.c
> +  AhciPeiBlockIo.h
>    AhciPeiPassThru.c
>    AhciPeiPassThru.h
>    AhciPeiS3.c
> @@ -54,6 +56,8 @@ [Ppis]
>    gEdkiiIoMmuPpiGuid                             ## CONSUMES
>    gEfiEndOfPeiSignalPpiGuid                      ## CONSUMES
>    gEdkiiPeiAtaPassThruPpiGuid                    ## SOMETIMES_PRODUCES
> +  gEfiPeiVirtualBlockIoPpiGuid                   ## SOMETIMES_PRODUCES
> +  gEfiPeiVirtualBlockIo2PpiGuid                  ## SOMETIMES_PRODUCES
>    gEdkiiPeiStorageSecurityCommandPpiGuid         ## SOMETIMES_PRODUCES
> 
>  [Guids]
> diff --git a/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.h
> b/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.h
> index e6a9c0a333..9a34dc6e4f 100644
> --- a/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.h
> +++ b/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.h
> @@ -19,6 +19,7 @@
>  #include <Ppi/IoMmu.h>
>  #include <Ppi/EndOfPeiPhase.h>
>  #include <Ppi/AtaPassThru.h>
> +#include <Ppi/BlockIo.h>
>  #include <Ppi/BlockIo2.h>
>  #include <Ppi/StorageSecurityCommand.h>
> 
> @@ -35,6 +36,7 @@
>  typedef struct _PEI_AHCI_CONTROLLER_PRIVATE_DATA
> PEI_AHCI_CONTROLLER_PRIVATE_DATA;
> 
>  #include "AhciPeiPassThru.h"
> +#include "AhciPeiBlockIo.h"
>  #include "AhciPeiStorageSecurity.h"
> 
>  //
> @@ -312,6 +314,8 @@ struct _PEI_AHCI_CONTROLLER_PRIVATE_DATA {
> 
>    EFI_ATA_PASS_THRU_MODE                AtaPassThruMode;
>    EDKII_PEI_ATA_PASS_THRU_PPI           AtaPassThruPpi;
> +  EFI_PEI_RECOVERY_BLOCK_IO_PPI         BlkIoPpi;
> +  EFI_PEI_RECOVERY_BLOCK_IO2_PPI        BlkIo2Ppi;
>    EDKII_PEI_STORAGE_SECURITY_CMD_PPI    StorageSecurityPpi;
>    EFI_PEI_PPI_DESCRIPTOR                AtaPassThruPpiList;
>    EFI_PEI_PPI_DESCRIPTOR                BlkIoPpiList;
> @@ -554,6 +558,32 @@ AhciModeInitialization (
>    );
> 
>  /**
> +  Transfer data from ATA device.
> +
> +  This function performs one ATA pass through transaction to transfer data
> from/to
> +  ATA device. It chooses the appropriate ATA command and protocol to
> invoke PassThru
> +  interface of ATA pass through.
> +
> +  @param[in]     DeviceData        A pointer to PEI_AHCI_ATA_DEVICE_DATA
> structure.
> +  @param[in,out] Buffer            The pointer to the current transaction buffer.
> +  @param[in]     StartLba          The starting logical block address to be
> accessed.
> +  @param[in]     TransferLength    The block number or sector count of the
> transfer.
> +  @param[in]     IsWrite           Indicates whether it is a write operation.
> +
> +  @retval EFI_SUCCESS    The data transfer is complete successfully.
> +  @return others         Some error occurs when transferring data.
> +
> +**/
> +EFI_STATUS
> +TransferAtaDevice (
> +  IN     PEI_AHCI_ATA_DEVICE_DATA    *DeviceData,
> +  IN OUT VOID                        *Buffer,
> +  IN     EFI_LBA                     StartLba,
> +  IN     UINT32                      TransferLength,
> +  IN     BOOLEAN                     IsWrite
> +  );
> +
> +/**
>    Trust transfer data from/to ATA device.
> 
>    This function performs one ATA pass through transaction to do a trust
> transfer
> diff --git a/MdeModulePkg/Bus/Ata/AhciPei/AhciPeiBlockIo.h
> b/MdeModulePkg/Bus/Ata/AhciPei/AhciPeiBlockIo.h
> new file mode 100644
> index 0000000000..5896ae5acf
> --- /dev/null
> +++ b/MdeModulePkg/Bus/Ata/AhciPei/AhciPeiBlockIo.h
> @@ -0,0 +1,257 @@
> +/** @file
> +  The AhciPei driver is used to manage ATA hard disk device working under
> AHCI
> +  mode at PEI phase.
> +
> +  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef _AHCI_PEI_BLOCKIO_H_
> +#define _AHCI_PEI_BLOCKIO_H_
> +
> +//
> +// ATA hard disk device for EFI_PEI_BLOCK_DEVICE_TYPE
> +//
> +#define EDKII_PEI_BLOCK_DEVICE_TYPE_ATA_HARD_DISK     8
> +
> +/**
> +  Gets the count of block I/O devices that one specific block driver detects.
> +
> +  This function is used for getting the count of block I/O devices that one
> +  specific block driver detects. If no device is detected, then the function
> +  will return zero.
> +
> +  @param[in]  PeiServices          General-purpose services that are available
> +                                   to every PEIM.
> +  @param[in]  This                 Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
> +                                   instance.
> +  @param[out] NumberBlockDevices   The number of block I/O devices
> discovered.
> +
> +  @retval     EFI_SUCCESS          The operation performed successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciBlockIoGetDeviceNo (
> +  IN  EFI_PEI_SERVICES               **PeiServices,
> +  IN  EFI_PEI_RECOVERY_BLOCK_IO_PPI  *This,
> +  OUT UINTN                          *NumberBlockDevices
> +  );
> +
> +/**
> +  Gets a block device's media information.
> +
> +  This function will provide the caller with the specified block device's media
> +  information. If the media changes, calling this function will update the
> media
> +  information accordingly.
> +
> +  @param[in]  PeiServices   General-purpose services that are available to
> every
> +                            PEIM
> +  @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
> instance.
> +  @param[in]  DeviceIndex   Specifies the block device to which the function
> wants
> +                            to talk. Because the driver that implements Block I/O
> +                            PPIs will manage multiple block devices, the PPIs that
> +                            want to talk to a single device must specify the
> +                            device index that was assigned during the enumeration
> +                            process. This index is a number from one to
> +                            NumberBlockDevices.
> +  @param[out] MediaInfo     The media information of the specified block
> media.
> +                            The caller is responsible for the ownership of this
> +                            data structure.
> +
> +  @par Note:
> +      The MediaInfo structure describes an enumeration of possible block
> device
> +      types.  This enumeration exists because no device paths are actually
> passed
> +      across interfaces that describe the type or class of hardware that is
> publishing
> +      the block I/O interface. This enumeration will allow for policy decisions
> +      in the Recovery PEIM, such as "Try to recover from legacy floppy first,
> +      LS-120 second, CD-ROM third." If there are multiple partitions
> abstracted
> +      by a given device type, they should be reported in ascending order; this
> +      order also applies to nested partitions, such as legacy MBR, where the
> +      outermost partitions would have precedence in the reporting order.
> The
> +      same logic applies to systems such as IDE that have precedence
> relationships
> +      like "Master/Slave" or "Primary/Secondary". The master device should
> be
> +      reported first, the slave second.
> +
> +  @retval EFI_SUCCESS        Media information about the specified block
> device
> +                             was obtained successfully.
> +  @retval EFI_DEVICE_ERROR   Cannot get the media information due to a
> hardware
> +                             error.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciBlockIoGetMediaInfo (
> +  IN  EFI_PEI_SERVICES               **PeiServices,
> +  IN  EFI_PEI_RECOVERY_BLOCK_IO_PPI  *This,
> +  IN  UINTN                          DeviceIndex,
> +  OUT EFI_PEI_BLOCK_IO_MEDIA         *MediaInfo
> +  );
> +
> +/**
> +  Reads the requested number of blocks from the specified block device.
> +
> +  The function reads the requested number of blocks from the device. All
> the
> +  blocks are read, or an error is returned. If there is no media in the device,
> +  the function returns EFI_NO_MEDIA.
> +
> +  @param[in]  PeiServices   General-purpose services that are available to
> +                            every PEIM.
> +  @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
> instance.
> +  @param[in]  DeviceIndex   Specifies the block device to which the function
> wants
> +                            to talk. Because the driver that implements Block I/O
> +                            PPIs will manage multiple block devices, PPIs that
> +                            want to talk to a single device must specify the device
> +                            index that was assigned during the enumeration process.
> +                            This index is a number from one to NumberBlockDevices.
> +  @param[in]  StartLBA      The starting logical block address (LBA) to read
> from
> +                            on the device
> +  @param[in]  BufferSize    The size of the Buffer in bytes. This number 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 the 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
> attempting
> +                                  to perform the read operation.
> +  @retval EFI_INVALID_PARAMETER   The read request contains LBAs that
> are not
> +                                  valid, or the buffer is not properly aligned.
> +  @retval EFI_NO_MEDIA            There is no media in the device.
> +  @retval EFI_BAD_BUFFER_SIZE     The BufferSize parameter is not a
> multiple of
> +                                  the intrinsic block size of the device.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciBlockIoReadBlocks (
> +  IN  EFI_PEI_SERVICES               **PeiServices,
> +  IN  EFI_PEI_RECOVERY_BLOCK_IO_PPI  *This,
> +  IN  UINTN                          DeviceIndex,
> +  IN  EFI_PEI_LBA                    StartLBA,
> +  IN  UINTN                          BufferSize,
> +  OUT VOID                           *Buffer
> +  );
> +
> +/**
> +  Gets the count of block I/O devices that one specific block driver detects.
> +
> +  This function is used for getting the count of block I/O devices that one
> +  specific block driver detects. If no device is detected, then the function
> +  will return zero.
> +
> +  @param[in]  PeiServices          General-purpose services that are available
> +                                   to every PEIM.
> +  @param[in]  This                 Indicates the
> EFI_PEI_RECOVERY_BLOCK_IO2_PPI
> +                                   instance.
> +  @param[out] NumberBlockDevices   The number of block I/O devices
> discovered.
> +
> +  @retval     EFI_SUCCESS          The operation performed successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciBlockIoGetDeviceNo2 (
> +  IN  EFI_PEI_SERVICES                **PeiServices,
> +  IN  EFI_PEI_RECOVERY_BLOCK_IO2_PPI  *This,
> +  OUT UINTN                           *NumberBlockDevices
> +  );
> +
> +/**
> +  Gets a block device's media information.
> +
> +  This function will provide the caller with the specified block device's media
> +  information. If the media changes, calling this function will update the
> media
> +  information accordingly.
> +
> +  @param[in]  PeiServices   General-purpose services that are available to
> every
> +                            PEIM
> +  @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI
> instance.
> +  @param[in]  DeviceIndex   Specifies the block device to which the function
> wants
> +                            to talk. Because the driver that implements Block I/O
> +                            PPIs will manage multiple block devices, the PPIs that
> +                            want to talk to a single device must specify the
> +                            device index that was assigned during the enumeration
> +                            process. This index is a number from one to
> +                            NumberBlockDevices.
> +  @param[out] MediaInfo     The media information of the specified block
> media.
> +                            The caller is responsible for the ownership of this
> +                            data structure.
> +
> +  @par Note:
> +      The MediaInfo structure describes an enumeration of possible block
> device
> +      types.  This enumeration exists because no device paths are actually
> passed
> +      across interfaces that describe the type or class of hardware that is
> publishing
> +      the block I/O interface. This enumeration will allow for policy decisions
> +      in the Recovery PEIM, such as "Try to recover from legacy floppy first,
> +      LS-120 second, CD-ROM third." If there are multiple partitions
> abstracted
> +      by a given device type, they should be reported in ascending order; this
> +      order also applies to nested partitions, such as legacy MBR, where the
> +      outermost partitions would have precedence in the reporting order.
> The
> +      same logic applies to systems such as IDE that have precedence
> relationships
> +      like "Master/Slave" or "Primary/Secondary". The master device should
> be
> +      reported first, the slave second.
> +
> +  @retval EFI_SUCCESS        Media information about the specified block
> device
> +                             was obtained successfully.
> +  @retval EFI_DEVICE_ERROR   Cannot get the media information due to a
> hardware
> +                             error.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciBlockIoGetMediaInfo2 (
> +  IN  EFI_PEI_SERVICES                **PeiServices,
> +  IN  EFI_PEI_RECOVERY_BLOCK_IO2_PPI  *This,
> +  IN  UINTN                           DeviceIndex,
> +  OUT EFI_PEI_BLOCK_IO2_MEDIA         *MediaInfo
> +  );
> +
> +/**
> +  Reads the requested number of blocks from the specified block device.
> +
> +  The function reads the requested number of blocks from the device. All
> the
> +  blocks are read, or an error is returned. If there is no media in the device,
> +  the function returns EFI_NO_MEDIA.
> +
> +  @param[in]  PeiServices   General-purpose services that are available to
> +                            every PEIM.
> +  @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI
> instance.
> +  @param[in]  DeviceIndex   Specifies the block device to which the function
> wants
> +                            to talk. Because the driver that implements Block I/O
> +                            PPIs will manage multiple block devices, PPIs that
> +                            want to talk to a single device must specify the device
> +                            index that was assigned during the enumeration process.
> +                            This index is a number from one to NumberBlockDevices.
> +  @param[in]  StartLBA      The starting logical block address (LBA) to read
> from
> +                            on the device
> +  @param[in]  BufferSize    The size of the Buffer in bytes. This number 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 the 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
> attempting
> +                                  to perform the read operation.
> +  @retval EFI_INVALID_PARAMETER   The read request contains LBAs that
> are not
> +                                  valid, or the buffer is not properly aligned.
> +  @retval EFI_NO_MEDIA            There is no media in the device.
> +  @retval EFI_BAD_BUFFER_SIZE     The BufferSize parameter is not a
> multiple of
> +                                  the intrinsic block size of the device.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciBlockIoReadBlocks2 (
> +  IN  EFI_PEI_SERVICES                **PeiServices,
> +  IN  EFI_PEI_RECOVERY_BLOCK_IO2_PPI  *This,
> +  IN  UINTN                           DeviceIndex,
> +  IN  EFI_PEI_LBA                     StartLBA,
> +  IN  UINTN                           BufferSize,
> +  OUT VOID                            *Buffer
> +  );
> +
> +#endif
> diff --git a/MdeModulePkg/Bus/Ata/AhciPei/AhciMode.c
> b/MdeModulePkg/Bus/Ata/AhciPei/AhciMode.c
> index 11754b3057..7287f8290e 100644
> --- a/MdeModulePkg/Bus/Ata/AhciPei/AhciMode.c
> +++ b/MdeModulePkg/Bus/Ata/AhciPei/AhciMode.c
> @@ -1873,6 +1873,124 @@ AhciModeInitialization (
>  }
> 
>  /**
> +  Transfer data from ATA device.
> +
> +  This function performs one ATA pass through transaction to transfer data
> from/to
> +  ATA device. It chooses the appropriate ATA command and protocol to
> invoke PassThru
> +  interface of ATA pass through.
> +
> +  @param[in]     DeviceData        A pointer to PEI_AHCI_ATA_DEVICE_DATA
> structure.
> +  @param[in,out] Buffer            The pointer to the current transaction buffer.
> +  @param[in]     StartLba          The starting logical block address to be
> accessed.
> +  @param[in]     TransferLength    The block number or sector count of the
> transfer.
> +  @param[in]     IsWrite           Indicates whether it is a write operation.
> +
> +  @retval EFI_SUCCESS    The data transfer is complete successfully.
> +  @return others         Some error occurs when transferring data.
> +
> +**/
> +EFI_STATUS
> +TransferAtaDevice (
> +  IN     PEI_AHCI_ATA_DEVICE_DATA    *DeviceData,
> +  IN OUT VOID                        *Buffer,
> +  IN     EFI_LBA                     StartLba,
> +  IN     UINT32                      TransferLength,
> +  IN     BOOLEAN                     IsWrite
> +  )
> +{
> +  PEI_AHCI_CONTROLLER_PRIVATE_DATA    *Private;
> +  EDKII_PEI_ATA_PASS_THRU_PPI         *AtaPassThru;
> +  EFI_ATA_COMMAND_BLOCK               Acb;
> +  EFI_ATA_PASS_THRU_COMMAND_PACKET    Packet;
> +
> +  Private     = DeviceData->Private;
> +  AtaPassThru = &Private->AtaPassThruPpi;
> +
> +  //
> +  // Ensure Lba48Bit and IsWrite are valid boolean values
> +  //
> +  ASSERT ((UINTN) DeviceData->Lba48Bit < 2);
> +  ASSERT ((UINTN) IsWrite < 2);
> +  if (((UINTN) DeviceData->Lba48Bit >= 2) ||
> +      ((UINTN) IsWrite >= 2)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // Prepare for ATA command block.
> +  //
> +  ZeroMem (&Acb, sizeof (EFI_ATA_COMMAND_BLOCK));
> +  Acb.AtaCommand = mAtaCommands[DeviceData->Lba48Bit][IsWrite];
> +  Acb.AtaSectorNumber = (UINT8) StartLba;
> +  Acb.AtaCylinderLow  = (UINT8) RShiftU64 (StartLba, 8);
> +  Acb.AtaCylinderHigh = (UINT8) RShiftU64 (StartLba, 16);
> +  Acb.AtaDeviceHead   = (UINT8) (BIT7 | BIT6 | BIT5 |
> +                                 (DeviceData->PortMultiplier == 0xFFFF ?
> +                                 0 : (DeviceData->PortMultiplier << 4)));
> +  Acb.AtaSectorCount  = (UINT8) TransferLength;
> +  if (DeviceData->Lba48Bit) {
> +    Acb.AtaSectorNumberExp = (UINT8) RShiftU64 (StartLba, 24);
> +    Acb.AtaCylinderLowExp  = (UINT8) RShiftU64 (StartLba, 32);
> +    Acb.AtaCylinderHighExp = (UINT8) RShiftU64 (StartLba, 40);
> +    Acb.AtaSectorCountExp  = (UINT8) (TransferLength >> 8);
> +  } else {
> +    Acb.AtaDeviceHead      = (UINT8) (Acb.AtaDeviceHead | RShiftU64
> (StartLba, 24));
> +  }
> +
> +  //
> +  // Prepare for ATA pass through packet.
> +  //
> +  ZeroMem (&Packet, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET));
> +  if (IsWrite) {
> +    Packet.OutDataBuffer     = Buffer;
> +    Packet.OutTransferLength = TransferLength;
> +  } else {
> +    Packet.InDataBuffer      = Buffer;
> +    Packet.InTransferLength  = TransferLength;
> +  }
> +  Packet.Asb      = NULL;
> +  Packet.Acb      = &Acb;
> +  Packet.Protocol = mAtaPassThruCmdProtocols[IsWrite];
> +  Packet.Length   = EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT;
> +  //
> +  // |------------------------|-----------------|
> +  // | ATA PIO Transfer Mode  |  Transfer Rate  |
> +  // |------------------------|-----------------|
> +  // |       PIO Mode 0       |  3.3Mbytes/sec  |
> +  // |------------------------|-----------------|
> +  // |       PIO Mode 1       |  5.2Mbytes/sec  |
> +  // |------------------------|-----------------|
> +  // |       PIO Mode 2       |  8.3Mbytes/sec  |
> +  // |------------------------|-----------------|
> +  // |       PIO Mode 3       | 11.1Mbytes/sec  |
> +  // |------------------------|-----------------|
> +  // |       PIO Mode 4       | 16.6Mbytes/sec  |
> +  // |------------------------|-----------------|
> +  //
> +  // As AtaBus is used to manage ATA devices, we have to use the lowest
> transfer
> +  // rate to calculate the possible maximum timeout value for each
> read/write
> +  // operation. The timout value is rounded up to nearest integar and here
> an
> +  // additional 30s is added to follow ATA spec in which it mentioned that
> the
> +  // device may take up to 30s to respond commands in the Standby/Idle
> mode.
> +  //
> +  // Calculate the maximum timeout value for PIO read/write operation.
> +  //
> +  Packet.Timeout = TIMER_PERIOD_SECONDS (
> +                     DivU64x32 (
> +                       MultU64x32 (TransferLength, DeviceData->Media.BlockSize),
> +                       3300000
> +                       ) + 31
> +                     );
> +
> +  return AtaPassThru->PassThru (
> +                        AtaPassThru,
> +                        DeviceData->Port,
> +                        DeviceData->PortMultiplier,
> +                        &Packet
> +                        );
> +}
> +
> +/**
>    Trust transfer data from/to ATA device.
> 
>    This function performs one ATA pass through transaction to do a trust
> transfer
> diff --git a/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.c
> b/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.c
> index 29e0aa7d65..31b072c118 100644
> --- a/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.c
> +++ b/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.c
> @@ -16,6 +16,18 @@ EFI_PEI_PPI_DESCRIPTOR
> mAhciAtaPassThruPpiListTemplate = {
>    NULL
>  };
> 
> +EFI_PEI_PPI_DESCRIPTOR  mAhciBlkIoPpiListTemplate = {
> +  (EFI_PEI_PPI_DESCRIPTOR_PPI |
> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> +  &gEfiPeiVirtualBlockIoPpiGuid,
> +  NULL
> +};
> +
> +EFI_PEI_PPI_DESCRIPTOR  mAhciBlkIo2PpiListTemplate = {
> +  (EFI_PEI_PPI_DESCRIPTOR_PPI |
> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> +  &gEfiPeiVirtualBlockIo2PpiGuid,
> +  NULL
> +};
> +
>  EFI_PEI_PPI_DESCRIPTOR  mAhciStorageSecurityPpiListTemplate = {
>    (EFI_PEI_PPI_DESCRIPTOR_PPI |
> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
>    &gEdkiiPeiStorageSecurityCommandPpiGuid,
> @@ -265,6 +277,29 @@ AtaAhciPeimEntry (
>      Private->AtaPassThruPpiList.Ppi       = &Private->AtaPassThruPpi;
>      PeiServicesInstallPpi (&Private->AtaPassThruPpiList);
> 
> +    Private->BlkIoPpi.GetNumberOfBlockDevices  = AhciBlockIoGetDeviceNo;
> +    Private->BlkIoPpi.GetBlockDeviceMediaInfo  = AhciBlockIoGetMediaInfo;
> +    Private->BlkIoPpi.ReadBlocks               = AhciBlockIoReadBlocks;
> +    CopyMem (
> +      &Private->BlkIoPpiList,
> +      &mAhciBlkIoPpiListTemplate,
> +      sizeof (EFI_PEI_PPI_DESCRIPTOR)
> +      );
> +    Private->BlkIoPpiList.Ppi                  = &Private->BlkIoPpi;
> +    PeiServicesInstallPpi (&Private->BlkIoPpiList);
> +
> +    Private->BlkIo2Ppi.Revision                =
> EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;
> +    Private->BlkIo2Ppi.GetNumberOfBlockDevices =
> AhciBlockIoGetDeviceNo2;
> +    Private->BlkIo2Ppi.GetBlockDeviceMediaInfo =
> AhciBlockIoGetMediaInfo2;
> +    Private->BlkIo2Ppi.ReadBlocks              = AhciBlockIoReadBlocks2;
> +    CopyMem (
> +      &Private->BlkIo2PpiList,
> +      &mAhciBlkIo2PpiListTemplate,
> +      sizeof (EFI_PEI_PPI_DESCRIPTOR)
> +      );
> +    Private->BlkIo2PpiList.Ppi                 = &Private->BlkIo2Ppi;
> +    PeiServicesInstallPpi (&Private->BlkIo2PpiList);
> +
>      if (Private->TrustComputingDevices != 0) {
>        DEBUG ((
>          DEBUG_INFO,
> diff --git a/MdeModulePkg/Bus/Ata/AhciPei/AhciPeiBlockIo.c
> b/MdeModulePkg/Bus/Ata/AhciPei/AhciPeiBlockIo.c
> new file mode 100644
> index 0000000000..e7c7a39539
> --- /dev/null
> +++ b/MdeModulePkg/Bus/Ata/AhciPei/AhciPeiBlockIo.c
> @@ -0,0 +1,516 @@
> +/** @file
> +  The AhciPei driver is used to manage ATA hard disk device working under
> AHCI
> +  mode at PEI phase.
> +
> +  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "AhciPei.h"
> +
> +/**
> +  Traverse the attached ATA devices list to find out the device with given
> index.
> +
> +  @param[in] Private        A pointer to the
> PEI_AHCI_CONTROLLER_PRIVATE_DATA
> +                            instance.
> +  @param[in] DeviceIndex    The device index.
> +
> +  @retval    The pointer to the PEI_AHCI_ATA_DEVICE_DATA structure of
> the device
> +             info to access.
> +
> +**/
> +PEI_AHCI_ATA_DEVICE_DATA *
> +SearchDeviceByIndex (
> +  IN PEI_AHCI_CONTROLLER_PRIVATE_DATA    *Private,
> +  IN UINTN                               DeviceIndex
> +  )
> +{
> +  PEI_AHCI_ATA_DEVICE_DATA    *DeviceData;
> +  LIST_ENTRY                  *Node;
> +
> +  if ((DeviceIndex == 0) || (DeviceIndex > Private->ActiveDevices)) {
> +    return NULL;
> +  }
> +
> +  Node = GetFirstNode (&Private->DeviceList);
> +  while (!IsNull (&Private->DeviceList, Node)) {
> +    DeviceData = AHCI_PEI_ATA_DEVICE_INFO_FROM_THIS (Node);
> +
> +    if (DeviceData->DeviceIndex == DeviceIndex) {
> +      return DeviceData;
> +    }
> +
> +    Node = GetNextNode (&Private->DeviceList, Node);
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Read a number of blocks from ATA device.
> +
> +  This function performs ATA pass through transactions to read data from
> ATA device.
> +  It may separate the read request into several ATA pass through
> transactions.
> +
> +  @param[in]     DeviceData        The pointer to the
> PEI_AHCI_ATA_DEVICE_DATA
> +                                   data structure.
> +  @param[in,out] Buffer            The pointer to the current transaction buffer.
> +  @param[in]     StartLba          The starting logical block address to be
> accessed.
> +  @param[in]     NumberOfBlocks    The block number or sector count of the
> transfer.
> +
> +  @retval EFI_SUCCESS    The data transfer is complete successfully.
> +  @return Others         Some error occurs when transferring data.
> +
> +**/
> +EFI_STATUS
> +AccessAtaDevice (
> +  IN     PEI_AHCI_ATA_DEVICE_DATA    *DeviceData,
> +  IN OUT UINT8                       *Buffer,
> +  IN     EFI_LBA                     StartLba,
> +  IN     UINTN                       NumberOfBlocks
> +  )
> +{
> +  EFI_STATUS    Status;
> +  UINTN         MaxTransferBlockNumber;
> +  UINTN         TransferBlockNumber;
> +  UINTN         BlockSize;
> +
> +  //
> +  // Ensure Lba48Bit is a valid boolean value
> +  //
> +  ASSERT ((UINTN) DeviceData->Lba48Bit < 2);
> +  if ((UINTN) DeviceData->Lba48Bit >= 2) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = EFI_SUCCESS;
> +  MaxTransferBlockNumber = mMaxTransferBlockNumber[DeviceData-
> >Lba48Bit];
> +  BlockSize              = DeviceData->Media.BlockSize;
> +
> +  do {
> +    if (NumberOfBlocks > MaxTransferBlockNumber) {
> +      TransferBlockNumber = MaxTransferBlockNumber;
> +      NumberOfBlocks     -= MaxTransferBlockNumber;
> +    } else  {
> +      TransferBlockNumber = NumberOfBlocks;
> +      NumberOfBlocks      = 0;
> +    }
> +    DEBUG ((
> +      DEBUG_BLKIO, "%a: Blocking AccessAtaDevice, TransferBlockNumber
> = %x; StartLba = %x\n",
> +      __FUNCTION__, TransferBlockNumber, StartLba
> +      ));
> +
> +    Status = TransferAtaDevice (
> +               DeviceData,
> +               Buffer,
> +               StartLba,
> +               (UINT32) TransferBlockNumber,
> +               FALSE  // Read
> +               );
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +
> +    StartLba += TransferBlockNumber;
> +    Buffer   += TransferBlockNumber * BlockSize;
> +  } while (NumberOfBlocks > 0);
> +
> +  return Status;
> +}
> +
> +/**
> +  Read specified bytes from Lba from the device.
> +
> +  @param[in]  DeviceData    The pointer to the
> PEI_AHCI_ATA_DEVICE_DATA data structure.
> +  @param[out] Buffer        The Buffer used to store the Data read from the
> device.
> +  @param[in]  StartLba      The start block number.
> +  @param[in]  BufferSize    Total bytes to be read.
> +
> +  @retval EFI_SUCCESS    Data are read from the device.
> +  @retval Others         Fail to read all the data.
> +
> +**/
> +EFI_STATUS
> +AhciRead (
> +  IN  PEI_AHCI_ATA_DEVICE_DATA    *DeviceData,
> +  OUT VOID                        *Buffer,
> +  IN  EFI_LBA                     StartLba,
> +  IN  UINTN                       BufferSize
> +  )
> +{
> +  EFI_STATUS    Status;
> +  UINTN         BlockSize;
> +  UINTN         NumberOfBlocks;
> +
> +  //
> +  // Check parameters.
> +  //
> +  if (Buffer == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (BufferSize == 0) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  BlockSize = DeviceData->Media.BlockSize;
> +  if ((BufferSize % BlockSize) != 0) {
> +    return EFI_BAD_BUFFER_SIZE;
> +  }
> +
> +  if (StartLba > DeviceData->Media.LastBlock) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  NumberOfBlocks  = BufferSize / BlockSize;
> +  if (NumberOfBlocks - 1 > DeviceData->Media.LastBlock - StartLba) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // Invoke low level AtaDevice Access Routine.
> +  //
> +  Status = AccessAtaDevice (DeviceData, Buffer, StartLba, NumberOfBlocks);
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  Gets the count of block I/O devices that one specific block driver detects.
> +
> +  This function is used for getting the count of block I/O devices that one
> +  specific block driver detects. If no device is detected, then the function
> +  will return zero.
> +
> +  @param[in]  PeiServices          General-purpose services that are available
> +                                   to every PEIM.
> +  @param[in]  This                 Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
> +                                   instance.
> +  @param[out] NumberBlockDevices   The number of block I/O devices
> discovered.
> +
> +  @retval     EFI_SUCCESS          The operation performed successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciBlockIoGetDeviceNo (
> +  IN  EFI_PEI_SERVICES               **PeiServices,
> +  IN  EFI_PEI_RECOVERY_BLOCK_IO_PPI  *This,
> +  OUT UINTN                          *NumberBlockDevices
> +  )
> +{
> +  PEI_AHCI_CONTROLLER_PRIVATE_DATA    *Private;
> +
> +  if (This == NULL || NumberBlockDevices == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO (This);
> +  *NumberBlockDevices = Private->ActiveDevices;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Gets a block device's media information.
> +
> +  This function will provide the caller with the specified block device's media
> +  information. If the media changes, calling this function will update the
> media
> +  information accordingly.
> +
> +  @param[in]  PeiServices   General-purpose services that are available to
> every
> +                            PEIM
> +  @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
> instance.
> +  @param[in]  DeviceIndex   Specifies the block device to which the function
> wants
> +                            to talk. Because the driver that implements Block I/O
> +                            PPIs will manage multiple block devices, the PPIs that
> +                            want to talk to a single device must specify the
> +                            device index that was assigned during the enumeration
> +                            process. This index is a number from one to
> +                            NumberBlockDevices.
> +  @param[out] MediaInfo     The media information of the specified block
> media.
> +                            The caller is responsible for the ownership of this
> +                            data structure.
> +
> +  @par Note:
> +      The MediaInfo structure describes an enumeration of possible block
> device
> +      types.  This enumeration exists because no device paths are actually
> passed
> +      across interfaces that describe the type or class of hardware that is
> publishing
> +      the block I/O interface. This enumeration will allow for policy decisions
> +      in the Recovery PEIM, such as "Try to recover from legacy floppy first,
> +      LS-120 second, CD-ROM third." If there are multiple partitions
> abstracted
> +      by a given device type, they should be reported in ascending order; this
> +      order also applies to nested partitions, such as legacy MBR, where the
> +      outermost partitions would have precedence in the reporting order.
> The
> +      same logic applies to systems such as IDE that have precedence
> relationships
> +      like "Master/Slave" or "Primary/Secondary". The master device should
> be
> +      reported first, the slave second.
> +
> +  @retval EFI_SUCCESS        Media information about the specified block
> device
> +                             was obtained successfully.
> +  @retval EFI_DEVICE_ERROR   Cannot get the media information due to a
> hardware
> +                             error.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciBlockIoGetMediaInfo (
> +  IN  EFI_PEI_SERVICES               **PeiServices,
> +  IN  EFI_PEI_RECOVERY_BLOCK_IO_PPI  *This,
> +  IN  UINTN                          DeviceIndex,
> +  OUT EFI_PEI_BLOCK_IO_MEDIA         *MediaInfo
> +  )
> +{
> +  PEI_AHCI_CONTROLLER_PRIVATE_DATA    *Private;
> +  PEI_AHCI_ATA_DEVICE_DATA            *DeviceData;
> +
> +  if (This == NULL || MediaInfo == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Private    = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO (This);
> +  DeviceData = SearchDeviceByIndex (Private, DeviceIndex);
> +  if (DeviceData == NULL) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  MediaInfo->DeviceType   = (EFI_PEI_BLOCK_DEVICE_TYPE)
> EDKII_PEI_BLOCK_DEVICE_TYPE_ATA_HARD_DISK;
> +  MediaInfo->MediaPresent = TRUE;
> +  MediaInfo->LastBlock    = (UINTN) DeviceData->Media.LastBlock;
> +  MediaInfo->BlockSize    = DeviceData->Media.BlockSize;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Reads the requested number of blocks from the specified block device.
> +
> +  The function reads the requested number of blocks from the device. All
> the
> +  blocks are read, or an error is returned. If there is no media in the device,
> +  the function returns EFI_NO_MEDIA.
> +
> +  @param[in]  PeiServices   General-purpose services that are available to
> +                            every PEIM.
> +  @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
> instance.
> +  @param[in]  DeviceIndex   Specifies the block device to which the function
> wants
> +                            to talk. Because the driver that implements Block I/O
> +                            PPIs will manage multiple block devices, PPIs that
> +                            want to talk to a single device must specify the device
> +                            index that was assigned during the enumeration process.
> +                            This index is a number from one to NumberBlockDevices.
> +  @param[in]  StartLBA      The starting logical block address (LBA) to read
> from
> +                            on the device
> +  @param[in]  BufferSize    The size of the Buffer in bytes. This number 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 the 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
> attempting
> +                                  to perform the read operation.
> +  @retval EFI_INVALID_PARAMETER   The read request contains LBAs that
> are not
> +                                  valid, or the buffer is not properly aligned.
> +  @retval EFI_NO_MEDIA            There is no media in the device.
> +  @retval EFI_BAD_BUFFER_SIZE     The BufferSize parameter is not a
> multiple of
> +                                  the intrinsic block size of the device.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciBlockIoReadBlocks (
> +  IN  EFI_PEI_SERVICES               **PeiServices,
> +  IN  EFI_PEI_RECOVERY_BLOCK_IO_PPI  *This,
> +  IN  UINTN                          DeviceIndex,
> +  IN  EFI_PEI_LBA                    StartLBA,
> +  IN  UINTN                          BufferSize,
> +  OUT VOID                           *Buffer
> +  )
> +{
> +  PEI_AHCI_CONTROLLER_PRIVATE_DATA    *Private;
> +  PEI_AHCI_ATA_DEVICE_DATA            *DeviceData;
> +
> +  if (This == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Private    = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO (This);
> +  DeviceData = SearchDeviceByIndex (Private, DeviceIndex);
> +  if (DeviceData == NULL) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  return AhciRead (DeviceData, Buffer, StartLBA, BufferSize);
> +}
> +
> +/**
> +  Gets the count of block I/O devices that one specific block driver detects.
> +
> +  This function is used for getting the count of block I/O devices that one
> +  specific block driver detects. If no device is detected, then the function
> +  will return zero.
> +
> +  @param[in]  PeiServices          General-purpose services that are available
> +                                   to every PEIM.
> +  @param[in]  This                 Indicates the
> EFI_PEI_RECOVERY_BLOCK_IO2_PPI
> +                                   instance.
> +  @param[out] NumberBlockDevices   The number of block I/O devices
> discovered.
> +
> +  @retval     EFI_SUCCESS          The operation performed successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciBlockIoGetDeviceNo2 (
> +  IN  EFI_PEI_SERVICES                **PeiServices,
> +  IN  EFI_PEI_RECOVERY_BLOCK_IO2_PPI  *This,
> +  OUT UINTN                           *NumberBlockDevices
> +  )
> +{
> +  PEI_AHCI_CONTROLLER_PRIVATE_DATA    *Private;
> +
> +  if (This == NULL || NumberBlockDevices == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2 (This);
> +  *NumberBlockDevices = Private->ActiveDevices;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Gets a block device's media information.
> +
> +  This function will provide the caller with the specified block device's media
> +  information. If the media changes, calling this function will update the
> media
> +  information accordingly.
> +
> +  @param[in]  PeiServices   General-purpose services that are available to
> every
> +                            PEIM
> +  @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI
> instance.
> +  @param[in]  DeviceIndex   Specifies the block device to which the function
> wants
> +                            to talk. Because the driver that implements Block I/O
> +                            PPIs will manage multiple block devices, the PPIs that
> +                            want to talk to a single device must specify the
> +                            device index that was assigned during the enumeration
> +                            process. This index is a number from one to
> +                            NumberBlockDevices.
> +  @param[out] MediaInfo     The media information of the specified block
> media.
> +                            The caller is responsible for the ownership of this
> +                            data structure.
> +
> +  @par Note:
> +      The MediaInfo structure describes an enumeration of possible block
> device
> +      types.  This enumeration exists because no device paths are actually
> passed
> +      across interfaces that describe the type or class of hardware that is
> publishing
> +      the block I/O interface. This enumeration will allow for policy decisions
> +      in the Recovery PEIM, such as "Try to recover from legacy floppy first,
> +      LS-120 second, CD-ROM third." If there are multiple partitions
> abstracted
> +      by a given device type, they should be reported in ascending order; this
> +      order also applies to nested partitions, such as legacy MBR, where the
> +      outermost partitions would have precedence in the reporting order.
> The
> +      same logic applies to systems such as IDE that have precedence
> relationships
> +      like "Master/Slave" or "Primary/Secondary". The master device should
> be
> +      reported first, the slave second.
> +
> +  @retval EFI_SUCCESS        Media information about the specified block
> device
> +                             was obtained successfully.
> +  @retval EFI_DEVICE_ERROR   Cannot get the media information due to a
> hardware
> +                             error.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciBlockIoGetMediaInfo2 (
> +  IN  EFI_PEI_SERVICES                **PeiServices,
> +  IN  EFI_PEI_RECOVERY_BLOCK_IO2_PPI  *This,
> +  IN  UINTN                           DeviceIndex,
> +  OUT EFI_PEI_BLOCK_IO2_MEDIA         *MediaInfo
> +  )
> +{
> +  PEI_AHCI_CONTROLLER_PRIVATE_DATA    *Private;
> +  PEI_AHCI_ATA_DEVICE_DATA            *DeviceData;
> +
> +  if (This == NULL || MediaInfo == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Private    = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2
> (This);
> +  DeviceData = SearchDeviceByIndex (Private, DeviceIndex);
> +  if (DeviceData == NULL) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  CopyMem (
> +    MediaInfo,
> +    &DeviceData->Media,
> +    sizeof (EFI_PEI_BLOCK_IO2_MEDIA)
> +    );
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Reads the requested number of blocks from the specified block device.
> +
> +  The function reads the requested number of blocks from the device. All
> the
> +  blocks are read, or an error is returned. If there is no media in the device,
> +  the function returns EFI_NO_MEDIA.
> +
> +  @param[in]  PeiServices   General-purpose services that are available to
> +                            every PEIM.
> +  @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI
> instance.
> +  @param[in]  DeviceIndex   Specifies the block device to which the function
> wants
> +                            to talk. Because the driver that implements Block I/O
> +                            PPIs will manage multiple block devices, PPIs that
> +                            want to talk to a single device must specify the device
> +                            index that was assigned during the enumeration process.
> +                            This index is a number from one to NumberBlockDevices.
> +  @param[in]  StartLBA      The starting logical block address (LBA) to read
> from
> +                            on the device
> +  @param[in]  BufferSize    The size of the Buffer in bytes. This number 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 the 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
> attempting
> +                                  to perform the read operation.
> +  @retval EFI_INVALID_PARAMETER   The read request contains LBAs that
> are not
> +                                  valid, or the buffer is not properly aligned.
> +  @retval EFI_NO_MEDIA            There is no media in the device.
> +  @retval EFI_BAD_BUFFER_SIZE     The BufferSize parameter is not a
> multiple of
> +                                  the intrinsic block size of the device.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +AhciBlockIoReadBlocks2 (
> +  IN  EFI_PEI_SERVICES                **PeiServices,
> +  IN  EFI_PEI_RECOVERY_BLOCK_IO2_PPI  *This,
> +  IN  UINTN                           DeviceIndex,
> +  IN  EFI_PEI_LBA                     StartLBA,
> +  IN  UINTN                           BufferSize,
> +  OUT VOID                            *Buffer
> +  )
> +{
> +  PEI_AHCI_CONTROLLER_PRIVATE_DATA    *Private;
> +
> +  if (This == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2 (This);
> +  return AhciBlockIoReadBlocks (
> +           PeiServices,
> +           &Private->BlkIoPpi,
> +           DeviceIndex,
> +           StartLBA,
> +           BufferSize,
> +           Buffer
> +           );
> +}
> --
> 2.12.0.windows.1
> 
> 
> 


      reply	other threads:[~2019-04-23 18:15 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-23  8:06 [PATCH v3 0/2] Add PEI BlockIO support for ATA AHCI mode devices Wu, Hao A
2019-04-23  8:06 ` [PATCH v3 1/2] MdeModulePkg/AhciPei: Limit max transfer blocknum for 48-bit address Wu, Hao A
2019-04-23 18:12   ` [edk2-devel] " Ni, Ray
2019-04-23  8:06 ` [PATCH v3 2/2] MdeModulePkg/AhciPei: Add PEI BlockIO support Wu, Hao A
2019-04-23 18:14   ` Ni, Ray [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=734D49CCEBEEF84792F5B80ED585239D5C0FEB4D@SHSMSX104.ccr.corp.intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox