2 The AhciPei driver is used to manage ATA hard disk device working under AHCI
5 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
14 Traverse the attached ATA devices list to find out the device with given index.
16 @param[in] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA
18 @param[in] DeviceIndex The device index.
20 @retval The pointer to the PEI_AHCI_ATA_DEVICE_DATA structure of the device
24 PEI_AHCI_ATA_DEVICE_DATA
*
26 IN PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
,
30 PEI_AHCI_ATA_DEVICE_DATA
*DeviceData
;
33 if ((DeviceIndex
== 0) || (DeviceIndex
> Private
->ActiveDevices
)) {
37 Node
= GetFirstNode (&Private
->DeviceList
);
38 while (!IsNull (&Private
->DeviceList
, Node
)) {
39 DeviceData
= AHCI_PEI_ATA_DEVICE_INFO_FROM_THIS (Node
);
41 if (DeviceData
->DeviceIndex
== DeviceIndex
) {
45 Node
= GetNextNode (&Private
->DeviceList
, Node
);
52 Read a number of blocks from ATA device.
54 This function performs ATA pass through transactions to read data from ATA device.
55 It may separate the read request into several ATA pass through transactions.
57 @param[in] DeviceData The pointer to the PEI_AHCI_ATA_DEVICE_DATA
59 @param[in,out] Buffer The pointer to the current transaction buffer.
60 @param[in] StartLba The starting logical block address to be accessed.
61 @param[in] NumberOfBlocks The block number or sector count of the transfer.
63 @retval EFI_SUCCESS The data transfer is complete successfully.
64 @return Others Some error occurs when transferring data.
69 IN PEI_AHCI_ATA_DEVICE_DATA
*DeviceData
,
72 IN UINTN NumberOfBlocks
76 UINTN MaxTransferBlockNumber
;
77 UINTN TransferBlockNumber
;
81 // Ensure Lba48Bit is a valid boolean value
83 ASSERT ((UINTN
) DeviceData
->Lba48Bit
< 2);
84 if ((UINTN
) DeviceData
->Lba48Bit
>= 2) {
85 return EFI_INVALID_PARAMETER
;
89 MaxTransferBlockNumber
= mMaxTransferBlockNumber
[DeviceData
->Lba48Bit
];
90 BlockSize
= DeviceData
->Media
.BlockSize
;
93 if (NumberOfBlocks
> MaxTransferBlockNumber
) {
94 TransferBlockNumber
= MaxTransferBlockNumber
;
95 NumberOfBlocks
-= MaxTransferBlockNumber
;
97 TransferBlockNumber
= NumberOfBlocks
;
101 DEBUG_BLKIO
, "%a: Blocking AccessAtaDevice, TransferBlockNumber = %x; StartLba = %x\n",
102 __FUNCTION__
, TransferBlockNumber
, StartLba
105 Status
= TransferAtaDevice (
109 (UINT32
) TransferBlockNumber
,
112 if (EFI_ERROR (Status
)) {
116 StartLba
+= TransferBlockNumber
;
117 Buffer
+= TransferBlockNumber
* BlockSize
;
118 } while (NumberOfBlocks
> 0);
124 Read specified bytes from Lba from the device.
126 @param[in] DeviceData The pointer to the PEI_AHCI_ATA_DEVICE_DATA data structure.
127 @param[out] Buffer The Buffer used to store the Data read from the device.
128 @param[in] StartLba The start block number.
129 @param[in] BufferSize Total bytes to be read.
131 @retval EFI_SUCCESS Data are read from the device.
132 @retval Others Fail to read all the data.
137 IN PEI_AHCI_ATA_DEVICE_DATA
*DeviceData
,
145 UINTN NumberOfBlocks
;
150 if (Buffer
== NULL
) {
151 return EFI_INVALID_PARAMETER
;
154 if (BufferSize
== 0) {
158 BlockSize
= DeviceData
->Media
.BlockSize
;
159 if ((BufferSize
% BlockSize
) != 0) {
160 return EFI_BAD_BUFFER_SIZE
;
163 if (StartLba
> DeviceData
->Media
.LastBlock
) {
164 return EFI_INVALID_PARAMETER
;
166 NumberOfBlocks
= BufferSize
/ BlockSize
;
167 if (NumberOfBlocks
- 1 > DeviceData
->Media
.LastBlock
- StartLba
) {
168 return EFI_INVALID_PARAMETER
;
172 // Invoke low level AtaDevice Access Routine.
174 Status
= AccessAtaDevice (DeviceData
, Buffer
, StartLba
, NumberOfBlocks
);
181 Gets the count of block I/O devices that one specific block driver detects.
183 This function is used for getting the count of block I/O devices that one
184 specific block driver detects. If no device is detected, then the function
187 @param[in] PeiServices General-purpose services that are available
189 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
191 @param[out] NumberBlockDevices The number of block I/O devices discovered.
193 @retval EFI_SUCCESS The operation performed successfully.
198 AhciBlockIoGetDeviceNo (
199 IN EFI_PEI_SERVICES
**PeiServices
,
200 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI
*This
,
201 OUT UINTN
*NumberBlockDevices
204 PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
;
206 if (This
== NULL
|| NumberBlockDevices
== NULL
) {
207 return EFI_INVALID_PARAMETER
;
210 Private
= GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO (This
);
211 *NumberBlockDevices
= Private
->ActiveDevices
;
217 Gets a block device's media information.
219 This function will provide the caller with the specified block device's media
220 information. If the media changes, calling this function will update the media
221 information accordingly.
223 @param[in] PeiServices General-purpose services that are available to every
225 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
226 @param[in] DeviceIndex Specifies the block device to which the function wants
227 to talk. Because the driver that implements Block I/O
228 PPIs will manage multiple block devices, the PPIs that
229 want to talk to a single device must specify the
230 device index that was assigned during the enumeration
231 process. This index is a number from one to
233 @param[out] MediaInfo The media information of the specified block media.
234 The caller is responsible for the ownership of this
238 The MediaInfo structure describes an enumeration of possible block device
239 types. This enumeration exists because no device paths are actually passed
240 across interfaces that describe the type or class of hardware that is publishing
241 the block I/O interface. This enumeration will allow for policy decisions
242 in the Recovery PEIM, such as "Try to recover from legacy floppy first,
243 LS-120 second, CD-ROM third." If there are multiple partitions abstracted
244 by a given device type, they should be reported in ascending order; this
245 order also applies to nested partitions, such as legacy MBR, where the
246 outermost partitions would have precedence in the reporting order. The
247 same logic applies to systems such as IDE that have precedence relationships
248 like "Master/Slave" or "Primary/Secondary". The master device should be
249 reported first, the slave second.
251 @retval EFI_SUCCESS Media information about the specified block device
252 was obtained successfully.
253 @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware
259 AhciBlockIoGetMediaInfo (
260 IN EFI_PEI_SERVICES
**PeiServices
,
261 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI
*This
,
262 IN UINTN DeviceIndex
,
263 OUT EFI_PEI_BLOCK_IO_MEDIA
*MediaInfo
266 PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
;
267 PEI_AHCI_ATA_DEVICE_DATA
*DeviceData
;
269 if (This
== NULL
|| MediaInfo
== NULL
) {
270 return EFI_INVALID_PARAMETER
;
273 Private
= GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO (This
);
274 DeviceData
= SearchDeviceByIndex (Private
, DeviceIndex
);
275 if (DeviceData
== NULL
) {
276 return EFI_NOT_FOUND
;
279 MediaInfo
->DeviceType
= (EFI_PEI_BLOCK_DEVICE_TYPE
) EDKII_PEI_BLOCK_DEVICE_TYPE_ATA_HARD_DISK
;
280 MediaInfo
->MediaPresent
= TRUE
;
281 MediaInfo
->LastBlock
= (UINTN
) DeviceData
->Media
.LastBlock
;
282 MediaInfo
->BlockSize
= DeviceData
->Media
.BlockSize
;
288 Reads the requested number of blocks from the specified block device.
290 The function reads the requested number of blocks from the device. All the
291 blocks are read, or an error is returned. If there is no media in the device,
292 the function returns EFI_NO_MEDIA.
294 @param[in] PeiServices General-purpose services that are available to
296 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
297 @param[in] DeviceIndex Specifies the block device to which the function wants
298 to talk. Because the driver that implements Block I/O
299 PPIs will manage multiple block devices, PPIs that
300 want to talk to a single device must specify the device
301 index that was assigned during the enumeration process.
302 This index is a number from one to NumberBlockDevices.
303 @param[in] StartLBA The starting logical block address (LBA) to read from
305 @param[in] BufferSize The size of the Buffer in bytes. This number must be
306 a multiple of the intrinsic block size of the device.
307 @param[out] Buffer A pointer to the destination buffer for the data.
308 The caller is responsible for the ownership of the
311 @retval EFI_SUCCESS The data was read correctly from the device.
312 @retval EFI_DEVICE_ERROR The device reported an error while attempting
313 to perform the read operation.
314 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
315 valid, or the buffer is not properly aligned.
316 @retval EFI_NO_MEDIA There is no media in the device.
317 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
318 the intrinsic block size of the device.
323 AhciBlockIoReadBlocks (
324 IN EFI_PEI_SERVICES
**PeiServices
,
325 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI
*This
,
326 IN UINTN DeviceIndex
,
327 IN EFI_PEI_LBA StartLBA
,
332 PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
;
333 PEI_AHCI_ATA_DEVICE_DATA
*DeviceData
;
336 return EFI_INVALID_PARAMETER
;
339 Private
= GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO (This
);
340 DeviceData
= SearchDeviceByIndex (Private
, DeviceIndex
);
341 if (DeviceData
== NULL
) {
342 return EFI_NOT_FOUND
;
345 return AhciRead (DeviceData
, Buffer
, StartLBA
, BufferSize
);
349 Gets the count of block I/O devices that one specific block driver detects.
351 This function is used for getting the count of block I/O devices that one
352 specific block driver detects. If no device is detected, then the function
355 @param[in] PeiServices General-purpose services that are available
357 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI
359 @param[out] NumberBlockDevices The number of block I/O devices discovered.
361 @retval EFI_SUCCESS The operation performed successfully.
366 AhciBlockIoGetDeviceNo2 (
367 IN EFI_PEI_SERVICES
**PeiServices
,
368 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI
*This
,
369 OUT UINTN
*NumberBlockDevices
372 PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
;
374 if (This
== NULL
|| NumberBlockDevices
== NULL
) {
375 return EFI_INVALID_PARAMETER
;
378 Private
= GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2 (This
);
379 *NumberBlockDevices
= Private
->ActiveDevices
;
385 Gets a block device's media information.
387 This function will provide the caller with the specified block device's media
388 information. If the media changes, calling this function will update the media
389 information accordingly.
391 @param[in] PeiServices General-purpose services that are available to every
393 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.
394 @param[in] DeviceIndex Specifies the block device to which the function wants
395 to talk. Because the driver that implements Block I/O
396 PPIs will manage multiple block devices, the PPIs that
397 want to talk to a single device must specify the
398 device index that was assigned during the enumeration
399 process. This index is a number from one to
401 @param[out] MediaInfo The media information of the specified block media.
402 The caller is responsible for the ownership of this
406 The MediaInfo structure describes an enumeration of possible block device
407 types. This enumeration exists because no device paths are actually passed
408 across interfaces that describe the type or class of hardware that is publishing
409 the block I/O interface. This enumeration will allow for policy decisions
410 in the Recovery PEIM, such as "Try to recover from legacy floppy first,
411 LS-120 second, CD-ROM third." If there are multiple partitions abstracted
412 by a given device type, they should be reported in ascending order; this
413 order also applies to nested partitions, such as legacy MBR, where the
414 outermost partitions would have precedence in the reporting order. The
415 same logic applies to systems such as IDE that have precedence relationships
416 like "Master/Slave" or "Primary/Secondary". The master device should be
417 reported first, the slave second.
419 @retval EFI_SUCCESS Media information about the specified block device
420 was obtained successfully.
421 @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware
427 AhciBlockIoGetMediaInfo2 (
428 IN EFI_PEI_SERVICES
**PeiServices
,
429 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI
*This
,
430 IN UINTN DeviceIndex
,
431 OUT EFI_PEI_BLOCK_IO2_MEDIA
*MediaInfo
434 PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
;
435 PEI_AHCI_ATA_DEVICE_DATA
*DeviceData
;
437 if (This
== NULL
|| MediaInfo
== NULL
) {
438 return EFI_INVALID_PARAMETER
;
441 Private
= GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2 (This
);
442 DeviceData
= SearchDeviceByIndex (Private
, DeviceIndex
);
443 if (DeviceData
== NULL
) {
444 return EFI_NOT_FOUND
;
450 sizeof (EFI_PEI_BLOCK_IO2_MEDIA
)
457 Reads the requested number of blocks from the specified block device.
459 The function reads the requested number of blocks from the device. All the
460 blocks are read, or an error is returned. If there is no media in the device,
461 the function returns EFI_NO_MEDIA.
463 @param[in] PeiServices General-purpose services that are available to
465 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.
466 @param[in] DeviceIndex Specifies the block device to which the function wants
467 to talk. Because the driver that implements Block I/O
468 PPIs will manage multiple block devices, PPIs that
469 want to talk to a single device must specify the device
470 index that was assigned during the enumeration process.
471 This index is a number from one to NumberBlockDevices.
472 @param[in] StartLBA The starting logical block address (LBA) to read from
474 @param[in] BufferSize The size of the Buffer in bytes. This number must be
475 a multiple of the intrinsic block size of the device.
476 @param[out] Buffer A pointer to the destination buffer for the data.
477 The caller is responsible for the ownership of the
480 @retval EFI_SUCCESS The data was read correctly from the device.
481 @retval EFI_DEVICE_ERROR The device reported an error while attempting
482 to perform the read operation.
483 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
484 valid, or the buffer is not properly aligned.
485 @retval EFI_NO_MEDIA There is no media in the device.
486 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
487 the intrinsic block size of the device.
492 AhciBlockIoReadBlocks2 (
493 IN EFI_PEI_SERVICES
**PeiServices
,
494 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI
*This
,
495 IN UINTN DeviceIndex
,
496 IN EFI_PEI_LBA StartLBA
,
501 PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
;
504 return EFI_INVALID_PARAMETER
;
507 Private
= GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2 (This
);
508 return AhciBlockIoReadBlocks (