From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 134.134.136.126, mailfrom: ray.ni@intel.com) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by groups.io with SMTP; Tue, 23 Apr 2019 11:15:02 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 23 Apr 2019 11:15:01 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.60,386,1549958400"; d="scan'208";a="164361105" Received: from fmsmsx108.amr.corp.intel.com ([10.18.124.206]) by fmsmga004.fm.intel.com with ESMTP; 23 Apr 2019 11:15:01 -0700 Received: from fmsmsx158.amr.corp.intel.com (10.18.116.75) by FMSMSX108.amr.corp.intel.com (10.18.124.206) with Microsoft SMTP Server (TLS) id 14.3.408.0; Tue, 23 Apr 2019 11:15:01 -0700 Received: from shsmsx152.ccr.corp.intel.com (10.239.6.52) by fmsmsx158.amr.corp.intel.com (10.18.116.75) with Microsoft SMTP Server (TLS) id 14.3.408.0; Tue, 23 Apr 2019 11:15:01 -0700 Received: from shsmsx104.ccr.corp.intel.com ([169.254.5.92]) by SHSMSX152.ccr.corp.intel.com ([169.254.6.42]) with mapi id 14.03.0415.000; Wed, 24 Apr 2019 02:14:58 +0800 From: "Ni, Ray" To: "devel@edk2.groups.io" , "Wu, Hao A" CC: "Dong, Eric" , "Wang, Jian J" Subject: Re: [edk2-devel] [PATCH v3 2/2] MdeModulePkg/AhciPei: Add PEI BlockIO support Thread-Topic: [edk2-devel] [PATCH v3 2/2] MdeModulePkg/AhciPei: Add PEI BlockIO support Thread-Index: AQHU+auDmUQI+v3jIUOA33Op2+ybmqZKDUYw Date: Tue, 23 Apr 2019 18:14:57 +0000 Deferred-Delivery: Tue, 23 Apr 2019 18:14:00 +0000 Message-ID: <734D49CCEBEEF84792F5B80ED585239D5C0FEB4D@SHSMSX104.ccr.corp.intel.com> References: <20190423080630.14992-1-hao.a.wu@intel.com> <20190423080630.14992-3-hao.a.wu@intel.com> In-Reply-To: <20190423080630.14992-3-hao.a.wu@intel.com> Accept-Language: en-US, zh-CN X-MS-Has-Attach: X-MS-TNEF-Correlator: x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiOGEyOGNkYzItOWQzYi00YWJhLWJmYTQtNmIzY2M2NTQzYzdhIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoid1pMbEZRTjVZQ1VwMElvNmRPeEFGdzhZZFwvWkZuN09aOFRUK1wvaTVERFdIMlFxYmZjd0FQaGczSnNyNzM4XC9RRCJ9 x-ctpclassification: CTP_NT dlp-product: dlpe-windows dlp-version: 11.0.600.7 dlp-reaction: no-action x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Return-Path: ray.ni@intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by: Ray Ni > -----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 ; Ni, Ray ; Dong, > Eric ; Wang, Jian J > Subject: [edk2-devel] [PATCH v3 2/2] MdeModulePkg/AhciPei: Add PEI > BlockIO support >=20 > REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D1483 >=20 > This commit will add the PEI BlockIO (2) PPIs support for AHCI mode ATA > devices. >=20 > 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: >=20 > EFI PEI Recovery Block IO PPI > EFI PEI Recovery Block IO2 PPI >=20 > Cc: Ray Ni > Cc: Eric Dong > Cc: Jian J Wang > Signed-off-by: Hao Wu > --- > 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(+) >=20 > 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 >=20 > [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 > #include > #include > +#include > #include > #include >=20 > @@ -35,6 +36,7 @@ > typedef struct _PEI_AHCI_CONTROLLER_PRIVATE_DATA > PEI_AHCI_CONTROLLER_PRIVATE_DATA; >=20 > #include "AhciPeiPassThru.h" > +#include "AhciPeiBlockIo.h" > #include "AhciPeiStorageSecurity.h" >=20 > // > @@ -312,6 +314,8 @@ struct _PEI_AHCI_CONTROLLER_PRIVATE_DATA { >=20 > 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 ( > ); >=20 > /** > + Transfer data from ATA device. > + > + This function performs one ATA pass through transaction to transfer d= ata > 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_DAT= A > structure. > + @param[in,out] Buffer The pointer to the current transacti= on buffer. > + @param[in] StartLba The starting logical block address t= o be > accessed. > + @param[in] TransferLength The block number or sector count of = the > transfer. > + @param[in] IsWrite Indicates whether it is a write oper= ation. > + > + @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. >=20 > 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 und= er > AHCI > + mode at PEI phase. > + > + Copyright (c) 2019, Intel Corporation. All rights reserved.
> + > + 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 de= tects. > + > + 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 fun= ction > + will return zero. > + > + @param[in] PeiServices General-purpose services that are av= ailable > + 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 fun= ction > wants > + to talk. Because the driver that implements= Block I/O > + PPIs will manage multiple block devices, th= e PPIs that > + want to talk to a single device must specif= y the > + device index that was assigned during the e= numeration > + process. This index is a number from one to > + NumberBlockDevices. > + @param[out] MediaInfo The media information of the specified bloc= k > media. > + The caller is responsible for the ownership= of this > + data structure. > + > + @par Note: > + The MediaInfo structure describes an enumeration of possible bloc= k > device > + types. This enumeration exists because no device paths are actua= lly > passed > + across interfaces that describe the type or class of hardware tha= t is > publishing > + the block I/O interface. This enumeration will allow for policy d= ecisions > + 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 orde= r; this > + order also applies to nested partitions, such as legacy MBR, wher= e 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 sho= uld > be > + reported first, the slave second. > + > + @retval EFI_SUCCESS Media information about the specified bloc= k > 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. Al= l > 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 fun= ction > wants > + to talk. Because the driver that implements= Block I/O > + PPIs will manage multiple block devices, PP= Is that > + want to talk to a single device must specif= y the device > + index that was assigned during the enumerat= ion process. > + This index is a number from one to NumberBl= ockDevices. > + @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 numbe= r must > be > + a multiple of the intrinsic block size of t= he 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 devic= e. > + > +**/ > +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 de= tects. > + > + 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 fun= ction > + will return zero. > + > + @param[in] PeiServices General-purpose services that are av= ailable > + 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_PP= I > instance. > + @param[in] DeviceIndex Specifies the block device to which the fun= ction > wants > + to talk. Because the driver that implements= Block I/O > + PPIs will manage multiple block devices, th= e PPIs that > + want to talk to a single device must specif= y the > + device index that was assigned during the e= numeration > + process. This index is a number from one to > + NumberBlockDevices. > + @param[out] MediaInfo The media information of the specified bloc= k > media. > + The caller is responsible for the ownership= of this > + data structure. > + > + @par Note: > + The MediaInfo structure describes an enumeration of possible bloc= k > device > + types. This enumeration exists because no device paths are actua= lly > passed > + across interfaces that describe the type or class of hardware tha= t is > publishing > + the block I/O interface. This enumeration will allow for policy d= ecisions > + 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 orde= r; this > + order also applies to nested partitions, such as legacy MBR, wher= e 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 sho= uld > be > + reported first, the slave second. > + > + @retval EFI_SUCCESS Media information about the specified bloc= k > 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. Al= l > 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_PP= I > instance. > + @param[in] DeviceIndex Specifies the block device to which the fun= ction > wants > + to talk. Because the driver that implements= Block I/O > + PPIs will manage multiple block devices, PP= Is that > + want to talk to a single device must specif= y the device > + index that was assigned during the enumerat= ion process. > + This index is a number from one to NumberBl= ockDevices. > + @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 numbe= r must > be > + a multiple of the intrinsic block size of t= he 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 devic= e. > + > +**/ > +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 ( > } >=20 > /** > + Transfer data from ATA device. > + > + This function performs one ATA pass through transaction to transfer d= ata > 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_DAT= A > structure. > + @param[in,out] Buffer The pointer to the current transacti= on buffer. > + @param[in] StartLba The starting logical block address t= o be > accessed. > + @param[in] TransferLength The block number or sector count of = the > transfer. > + @param[in] IsWrite Indicates whether it is a write oper= ation. > + > + @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 =3D DeviceData->Private; > + AtaPassThru =3D &Private->AtaPassThruPpi; > + > + // > + // Ensure Lba48Bit and IsWrite are valid boolean values > + // > + ASSERT ((UINTN) DeviceData->Lba48Bit < 2); > + ASSERT ((UINTN) IsWrite < 2); > + if (((UINTN) DeviceData->Lba48Bit >=3D 2) || > + ((UINTN) IsWrite >=3D 2)) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Prepare for ATA command block. > + // > + ZeroMem (&Acb, sizeof (EFI_ATA_COMMAND_BLOCK)); > + Acb.AtaCommand =3D mAtaCommands[DeviceData->Lba48Bit][IsWrite]; > + Acb.AtaSectorNumber =3D (UINT8) StartLba; > + Acb.AtaCylinderLow =3D (UINT8) RShiftU64 (StartLba, 8); > + Acb.AtaCylinderHigh =3D (UINT8) RShiftU64 (StartLba, 16); > + Acb.AtaDeviceHead =3D (UINT8) (BIT7 | BIT6 | BIT5 | > + (DeviceData->PortMultiplier =3D=3D 0xF= FFF ? > + 0 : (DeviceData->PortMultiplier << 4))= ); > + Acb.AtaSectorCount =3D (UINT8) TransferLength; > + if (DeviceData->Lba48Bit) { > + Acb.AtaSectorNumberExp =3D (UINT8) RShiftU64 (StartLba, 24); > + Acb.AtaCylinderLowExp =3D (UINT8) RShiftU64 (StartLba, 32); > + Acb.AtaCylinderHighExp =3D (UINT8) RShiftU64 (StartLba, 40); > + Acb.AtaSectorCountExp =3D (UINT8) (TransferLength >> 8); > + } else { > + Acb.AtaDeviceHead =3D (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 =3D Buffer; > + Packet.OutTransferLength =3D TransferLength; > + } else { > + Packet.InDataBuffer =3D Buffer; > + Packet.InTransferLength =3D TransferLength; > + } > + Packet.Asb =3D NULL; > + Packet.Acb =3D &Acb; > + Packet.Protocol =3D mAtaPassThruCmdProtocols[IsWrite]; > + Packet.Length =3D 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 h= ere > an > + // additional 30s is added to follow ATA spec in which it mentioned t= hat > 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 =3D TIMER_PERIOD_SECONDS ( > + DivU64x32 ( > + MultU64x32 (TransferLength, DeviceData->Media.Bl= ockSize), > + 3300000 > + ) + 31 > + ); > + > + return AtaPassThru->PassThru ( > + AtaPassThru, > + DeviceData->Port, > + DeviceData->PortMultiplier, > + &Packet > + ); > +} > + > +/** > Trust transfer data from/to ATA device. >=20 > 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 =3D { > NULL > }; >=20 > +EFI_PEI_PPI_DESCRIPTOR mAhciBlkIoPpiListTemplate =3D { > + (EFI_PEI_PPI_DESCRIPTOR_PPI | > EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), > + &gEfiPeiVirtualBlockIoPpiGuid, > + NULL > +}; > + > +EFI_PEI_PPI_DESCRIPTOR mAhciBlkIo2PpiListTemplate =3D { > + (EFI_PEI_PPI_DESCRIPTOR_PPI | > EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), > + &gEfiPeiVirtualBlockIo2PpiGuid, > + NULL > +}; > + > EFI_PEI_PPI_DESCRIPTOR mAhciStorageSecurityPpiListTemplate =3D { > (EFI_PEI_PPI_DESCRIPTOR_PPI | > EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), > &gEdkiiPeiStorageSecurityCommandPpiGuid, > @@ -265,6 +277,29 @@ AtaAhciPeimEntry ( > Private->AtaPassThruPpiList.Ppi =3D &Private->AtaPassThruPpi; > PeiServicesInstallPpi (&Private->AtaPassThruPpiList); >=20 > + Private->BlkIoPpi.GetNumberOfBlockDevices =3D AhciBlockIoGetDevice= No; > + Private->BlkIoPpi.GetBlockDeviceMediaInfo =3D AhciBlockIoGetMediaI= nfo; > + Private->BlkIoPpi.ReadBlocks =3D AhciBlockIoReadBlock= s; > + CopyMem ( > + &Private->BlkIoPpiList, > + &mAhciBlkIoPpiListTemplate, > + sizeof (EFI_PEI_PPI_DESCRIPTOR) > + ); > + Private->BlkIoPpiList.Ppi =3D &Private->BlkIoPpi; > + PeiServicesInstallPpi (&Private->BlkIoPpiList); > + > + Private->BlkIo2Ppi.Revision =3D > EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION; > + Private->BlkIo2Ppi.GetNumberOfBlockDevices =3D > AhciBlockIoGetDeviceNo2; > + Private->BlkIo2Ppi.GetBlockDeviceMediaInfo =3D > AhciBlockIoGetMediaInfo2; > + Private->BlkIo2Ppi.ReadBlocks =3D AhciBlockIoReadBlock= s2; > + CopyMem ( > + &Private->BlkIo2PpiList, > + &mAhciBlkIo2PpiListTemplate, > + sizeof (EFI_PEI_PPI_DESCRIPTOR) > + ); > + Private->BlkIo2PpiList.Ppi =3D &Private->BlkIo2Ppi; > + PeiServicesInstallPpi (&Private->BlkIo2PpiList); > + > if (Private->TrustComputingDevices !=3D 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 und= er > AHCI > + mode at PEI phase. > + > + Copyright (c) 2019, Intel Corporation. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "AhciPei.h" > + > +/** > + Traverse the attached ATA devices list to find out the device with gi= ven > 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 =3D=3D 0) || (DeviceIndex > Private->ActiveDevices))= { > + return NULL; > + } > + > + Node =3D GetFirstNode (&Private->DeviceList); > + while (!IsNull (&Private->DeviceList, Node)) { > + DeviceData =3D AHCI_PEI_ATA_DEVICE_INFO_FROM_THIS (Node); > + > + if (DeviceData->DeviceIndex =3D=3D DeviceIndex) { > + return DeviceData; > + } > + > + Node =3D GetNextNode (&Private->DeviceList, Node); > + } > + > + return NULL; > +} > + > +/** > + Read a number of blocks from ATA device. > + > + This function performs ATA pass through transactions to read data fro= m > 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 transacti= on buffer. > + @param[in] StartLba The starting logical block address t= o 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 >=3D 2) { > + return EFI_INVALID_PARAMETER; > + } > + > + Status =3D EFI_SUCCESS; > + MaxTransferBlockNumber =3D mMaxTransferBlockNumber[DeviceData- > >Lba48Bit]; > + BlockSize =3D DeviceData->Media.BlockSize; > + > + do { > + if (NumberOfBlocks > MaxTransferBlockNumber) { > + TransferBlockNumber =3D MaxTransferBlockNumber; > + NumberOfBlocks -=3D MaxTransferBlockNumber; > + } else { > + TransferBlockNumber =3D NumberOfBlocks; > + NumberOfBlocks =3D 0; > + } > + DEBUG (( > + DEBUG_BLKIO, "%a: Blocking AccessAtaDevice, TransferBlockNumber > =3D %x; StartLba =3D %x\n", > + __FUNCTION__, TransferBlockNumber, StartLba > + )); > + > + Status =3D TransferAtaDevice ( > + DeviceData, > + Buffer, > + StartLba, > + (UINT32) TransferBlockNumber, > + FALSE // Read > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + StartLba +=3D TransferBlockNumber; > + Buffer +=3D 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 =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (BufferSize =3D=3D 0) { > + return EFI_SUCCESS; > + } > + > + BlockSize =3D DeviceData->Media.BlockSize; > + if ((BufferSize % BlockSize) !=3D 0) { > + return EFI_BAD_BUFFER_SIZE; > + } > + > + if (StartLba > DeviceData->Media.LastBlock) { > + return EFI_INVALID_PARAMETER; > + } > + NumberOfBlocks =3D BufferSize / BlockSize; > + if (NumberOfBlocks - 1 > DeviceData->Media.LastBlock - StartLba) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Invoke low level AtaDevice Access Routine. > + // > + Status =3D AccessAtaDevice (DeviceData, Buffer, StartLba, NumberOfBlo= cks); > + > + return Status; > +} > + > + > +/** > + Gets the count of block I/O devices that one specific block driver de= tects. > + > + 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 fun= ction > + will return zero. > + > + @param[in] PeiServices General-purpose services that are av= ailable > + 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 =3D=3D NULL || NumberBlockDevices =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + Private =3D GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO (This); > + *NumberBlockDevices =3D 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 fun= ction > wants > + to talk. Because the driver that implements= Block I/O > + PPIs will manage multiple block devices, th= e PPIs that > + want to talk to a single device must specif= y the > + device index that was assigned during the e= numeration > + process. This index is a number from one to > + NumberBlockDevices. > + @param[out] MediaInfo The media information of the specified bloc= k > media. > + The caller is responsible for the ownership= of this > + data structure. > + > + @par Note: > + The MediaInfo structure describes an enumeration of possible bloc= k > device > + types. This enumeration exists because no device paths are actua= lly > passed > + across interfaces that describe the type or class of hardware tha= t is > publishing > + the block I/O interface. This enumeration will allow for policy d= ecisions > + 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 orde= r; this > + order also applies to nested partitions, such as legacy MBR, wher= e 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 sho= uld > be > + reported first, the slave second. > + > + @retval EFI_SUCCESS Media information about the specified bloc= k > 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 =3D=3D NULL || MediaInfo =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + Private =3D GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO (This); > + DeviceData =3D SearchDeviceByIndex (Private, DeviceIndex); > + if (DeviceData =3D=3D NULL) { > + return EFI_NOT_FOUND; > + } > + > + MediaInfo->DeviceType =3D (EFI_PEI_BLOCK_DEVICE_TYPE) > EDKII_PEI_BLOCK_DEVICE_TYPE_ATA_HARD_DISK; > + MediaInfo->MediaPresent =3D TRUE; > + MediaInfo->LastBlock =3D (UINTN) DeviceData->Media.LastBlock; > + MediaInfo->BlockSize =3D 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. Al= l > 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 fun= ction > wants > + to talk. Because the driver that implements= Block I/O > + PPIs will manage multiple block devices, PP= Is that > + want to talk to a single device must specif= y the device > + index that was assigned during the enumerat= ion process. > + This index is a number from one to NumberBl= ockDevices. > + @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 numbe= r must > be > + a multiple of the intrinsic block size of t= he 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 devic= e. > + > +**/ > +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 =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + Private =3D GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO (This); > + DeviceData =3D SearchDeviceByIndex (Private, DeviceIndex); > + if (DeviceData =3D=3D NULL) { > + return EFI_NOT_FOUND; > + } > + > + return AhciRead (DeviceData, Buffer, StartLBA, BufferSize); > +} > + > +/** > + Gets the count of block I/O devices that one specific block driver de= tects. > + > + 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 fun= ction > + will return zero. > + > + @param[in] PeiServices General-purpose services that are av= ailable > + 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 =3D=3D NULL || NumberBlockDevices =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + Private =3D GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2 (This); > + *NumberBlockDevices =3D 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_PP= I > instance. > + @param[in] DeviceIndex Specifies the block device to which the fun= ction > wants > + to talk. Because the driver that implements= Block I/O > + PPIs will manage multiple block devices, th= e PPIs that > + want to talk to a single device must specif= y the > + device index that was assigned during the e= numeration > + process. This index is a number from one to > + NumberBlockDevices. > + @param[out] MediaInfo The media information of the specified bloc= k > media. > + The caller is responsible for the ownership= of this > + data structure. > + > + @par Note: > + The MediaInfo structure describes an enumeration of possible bloc= k > device > + types. This enumeration exists because no device paths are actua= lly > passed > + across interfaces that describe the type or class of hardware tha= t is > publishing > + the block I/O interface. This enumeration will allow for policy d= ecisions > + 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 orde= r; this > + order also applies to nested partitions, such as legacy MBR, wher= e 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 sho= uld > be > + reported first, the slave second. > + > + @retval EFI_SUCCESS Media information about the specified bloc= k > 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 =3D=3D NULL || MediaInfo =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + Private =3D GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2 > (This); > + DeviceData =3D SearchDeviceByIndex (Private, DeviceIndex); > + if (DeviceData =3D=3D 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. Al= l > 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_PP= I > instance. > + @param[in] DeviceIndex Specifies the block device to which the fun= ction > wants > + to talk. Because the driver that implements= Block I/O > + PPIs will manage multiple block devices, PP= Is that > + want to talk to a single device must specif= y the device > + index that was assigned during the enumerat= ion process. > + This index is a number from one to NumberBl= ockDevices. > + @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 numbe= r must > be > + a multiple of the intrinsic block size of t= he 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 devic= e. > + > +**/ > +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 =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + Private =3D GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2 (This); > + return AhciBlockIoReadBlocks ( > + PeiServices, > + &Private->BlkIoPpi, > + DeviceIndex, > + StartLBA, > + BufferSize, > + Buffer > + ); > +} > -- > 2.12.0.windows.1 >=20 >=20 >=20