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
;
103 "%a: Blocking AccessAtaDevice, TransferBlockNumber = %x; StartLba = %x\n",
109 Status
= TransferAtaDevice (
113 (UINT32
)TransferBlockNumber
,
116 if (EFI_ERROR (Status
)) {
120 StartLba
+= TransferBlockNumber
;
121 Buffer
+= TransferBlockNumber
* BlockSize
;
122 } while (NumberOfBlocks
> 0);
128 Read specified bytes from Lba from the device.
130 @param[in] DeviceData The pointer to the PEI_AHCI_ATA_DEVICE_DATA data structure.
131 @param[out] Buffer The Buffer used to store the Data read from the device.
132 @param[in] StartLba The start block number.
133 @param[in] BufferSize Total bytes to be read.
135 @retval EFI_SUCCESS Data are read from the device.
136 @retval Others Fail to read all the data.
141 IN PEI_AHCI_ATA_DEVICE_DATA
*DeviceData
,
149 UINTN NumberOfBlocks
;
154 if (Buffer
== NULL
) {
155 return EFI_INVALID_PARAMETER
;
158 if (BufferSize
== 0) {
162 BlockSize
= DeviceData
->Media
.BlockSize
;
163 if ((BufferSize
% BlockSize
) != 0) {
164 return EFI_BAD_BUFFER_SIZE
;
167 if (StartLba
> DeviceData
->Media
.LastBlock
) {
168 return EFI_INVALID_PARAMETER
;
171 NumberOfBlocks
= BufferSize
/ BlockSize
;
172 if (NumberOfBlocks
- 1 > DeviceData
->Media
.LastBlock
- StartLba
) {
173 return EFI_INVALID_PARAMETER
;
177 // Invoke low level AtaDevice Access Routine.
179 Status
= AccessAtaDevice (DeviceData
, Buffer
, StartLba
, NumberOfBlocks
);
185 Gets the count of block I/O devices that one specific block driver detects.
187 This function is used for getting the count of block I/O devices that one
188 specific block driver detects. If no device is detected, then the function
191 @param[in] PeiServices General-purpose services that are available
193 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
195 @param[out] NumberBlockDevices The number of block I/O devices discovered.
197 @retval EFI_SUCCESS The operation performed successfully.
202 AhciBlockIoGetDeviceNo (
203 IN EFI_PEI_SERVICES
**PeiServices
,
204 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI
*This
,
205 OUT UINTN
*NumberBlockDevices
208 PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
;
210 if ((This
== NULL
) || (NumberBlockDevices
== NULL
)) {
211 return EFI_INVALID_PARAMETER
;
214 Private
= GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO (This
);
215 *NumberBlockDevices
= Private
->ActiveDevices
;
221 Gets a block device's media information.
223 This function will provide the caller with the specified block device's media
224 information. If the media changes, calling this function will update the media
225 information accordingly.
227 @param[in] PeiServices General-purpose services that are available to every
229 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
230 @param[in] DeviceIndex Specifies the block device to which the function wants
231 to talk. Because the driver that implements Block I/O
232 PPIs will manage multiple block devices, the PPIs that
233 want to talk to a single device must specify the
234 device index that was assigned during the enumeration
235 process. This index is a number from one to
237 @param[out] MediaInfo The media information of the specified block media.
238 The caller is responsible for the ownership of this
242 The MediaInfo structure describes an enumeration of possible block device
243 types. This enumeration exists because no device paths are actually passed
244 across interfaces that describe the type or class of hardware that is publishing
245 the block I/O interface. This enumeration will allow for policy decisions
246 in the Recovery PEIM, such as "Try to recover from legacy floppy first,
247 LS-120 second, CD-ROM third." If there are multiple partitions abstracted
248 by a given device type, they should be reported in ascending order; this
249 order also applies to nested partitions, such as legacy MBR, where the
250 outermost partitions would have precedence in the reporting order. The
251 same logic applies to systems such as IDE that have precedence relationships
252 like "Master/Slave" or "Primary/Secondary". The master device should be
253 reported first, the slave second.
255 @retval EFI_SUCCESS Media information about the specified block device
256 was obtained successfully.
257 @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware
263 AhciBlockIoGetMediaInfo (
264 IN EFI_PEI_SERVICES
**PeiServices
,
265 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI
*This
,
266 IN UINTN DeviceIndex
,
267 OUT EFI_PEI_BLOCK_IO_MEDIA
*MediaInfo
270 PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
;
271 PEI_AHCI_ATA_DEVICE_DATA
*DeviceData
;
273 if ((This
== NULL
) || (MediaInfo
== NULL
)) {
274 return EFI_INVALID_PARAMETER
;
277 Private
= GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO (This
);
278 DeviceData
= SearchDeviceByIndex (Private
, DeviceIndex
);
279 if (DeviceData
== NULL
) {
280 return EFI_NOT_FOUND
;
283 MediaInfo
->DeviceType
= (EFI_PEI_BLOCK_DEVICE_TYPE
)EDKII_PEI_BLOCK_DEVICE_TYPE_ATA_HARD_DISK
;
284 MediaInfo
->MediaPresent
= TRUE
;
285 MediaInfo
->LastBlock
= (UINTN
)DeviceData
->Media
.LastBlock
;
286 MediaInfo
->BlockSize
= DeviceData
->Media
.BlockSize
;
292 Reads the requested number of blocks from the specified block device.
294 The function reads the requested number of blocks from the device. All the
295 blocks are read, or an error is returned. If there is no media in the device,
296 the function returns EFI_NO_MEDIA.
298 @param[in] PeiServices General-purpose services that are available to
300 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
301 @param[in] DeviceIndex Specifies the block device to which the function wants
302 to talk. Because the driver that implements Block I/O
303 PPIs will manage multiple block devices, PPIs that
304 want to talk to a single device must specify the device
305 index that was assigned during the enumeration process.
306 This index is a number from one to NumberBlockDevices.
307 @param[in] StartLBA The starting logical block address (LBA) to read from
309 @param[in] BufferSize The size of the Buffer in bytes. This number must be
310 a multiple of the intrinsic block size of the device.
311 @param[out] Buffer A pointer to the destination buffer for the data.
312 The caller is responsible for the ownership of the
315 @retval EFI_SUCCESS The data was read correctly from the device.
316 @retval EFI_DEVICE_ERROR The device reported an error while attempting
317 to perform the read operation.
318 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
319 valid, or the buffer is not properly aligned.
320 @retval EFI_NO_MEDIA There is no media in the device.
321 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
322 the intrinsic block size of the device.
327 AhciBlockIoReadBlocks (
328 IN EFI_PEI_SERVICES
**PeiServices
,
329 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI
*This
,
330 IN UINTN DeviceIndex
,
331 IN EFI_PEI_LBA StartLBA
,
336 PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
;
337 PEI_AHCI_ATA_DEVICE_DATA
*DeviceData
;
340 return EFI_INVALID_PARAMETER
;
343 Private
= GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO (This
);
344 DeviceData
= SearchDeviceByIndex (Private
, DeviceIndex
);
345 if (DeviceData
== NULL
) {
346 return EFI_NOT_FOUND
;
349 return AhciRead (DeviceData
, Buffer
, StartLBA
, BufferSize
);
353 Gets the count of block I/O devices that one specific block driver detects.
355 This function is used for getting the count of block I/O devices that one
356 specific block driver detects. If no device is detected, then the function
359 @param[in] PeiServices General-purpose services that are available
361 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI
363 @param[out] NumberBlockDevices The number of block I/O devices discovered.
365 @retval EFI_SUCCESS The operation performed successfully.
370 AhciBlockIoGetDeviceNo2 (
371 IN EFI_PEI_SERVICES
**PeiServices
,
372 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI
*This
,
373 OUT UINTN
*NumberBlockDevices
376 PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
;
378 if ((This
== NULL
) || (NumberBlockDevices
== NULL
)) {
379 return EFI_INVALID_PARAMETER
;
382 Private
= GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2 (This
);
383 *NumberBlockDevices
= Private
->ActiveDevices
;
389 Gets a block device's media information.
391 This function will provide the caller with the specified block device's media
392 information. If the media changes, calling this function will update the media
393 information accordingly.
395 @param[in] PeiServices General-purpose services that are available to every
397 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.
398 @param[in] DeviceIndex Specifies the block device to which the function wants
399 to talk. Because the driver that implements Block I/O
400 PPIs will manage multiple block devices, the PPIs that
401 want to talk to a single device must specify the
402 device index that was assigned during the enumeration
403 process. This index is a number from one to
405 @param[out] MediaInfo The media information of the specified block media.
406 The caller is responsible for the ownership of this
410 The MediaInfo structure describes an enumeration of possible block device
411 types. This enumeration exists because no device paths are actually passed
412 across interfaces that describe the type or class of hardware that is publishing
413 the block I/O interface. This enumeration will allow for policy decisions
414 in the Recovery PEIM, such as "Try to recover from legacy floppy first,
415 LS-120 second, CD-ROM third." If there are multiple partitions abstracted
416 by a given device type, they should be reported in ascending order; this
417 order also applies to nested partitions, such as legacy MBR, where the
418 outermost partitions would have precedence in the reporting order. The
419 same logic applies to systems such as IDE that have precedence relationships
420 like "Master/Slave" or "Primary/Secondary". The master device should be
421 reported first, the slave second.
423 @retval EFI_SUCCESS Media information about the specified block device
424 was obtained successfully.
425 @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware
431 AhciBlockIoGetMediaInfo2 (
432 IN EFI_PEI_SERVICES
**PeiServices
,
433 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI
*This
,
434 IN UINTN DeviceIndex
,
435 OUT EFI_PEI_BLOCK_IO2_MEDIA
*MediaInfo
438 PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
;
439 PEI_AHCI_ATA_DEVICE_DATA
*DeviceData
;
441 if ((This
== NULL
) || (MediaInfo
== NULL
)) {
442 return EFI_INVALID_PARAMETER
;
445 Private
= GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2 (This
);
446 DeviceData
= SearchDeviceByIndex (Private
, DeviceIndex
);
447 if (DeviceData
== NULL
) {
448 return EFI_NOT_FOUND
;
454 sizeof (EFI_PEI_BLOCK_IO2_MEDIA
)
461 Reads the requested number of blocks from the specified block device.
463 The function reads the requested number of blocks from the device. All the
464 blocks are read, or an error is returned. If there is no media in the device,
465 the function returns EFI_NO_MEDIA.
467 @param[in] PeiServices General-purpose services that are available to
469 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.
470 @param[in] DeviceIndex Specifies the block device to which the function wants
471 to talk. Because the driver that implements Block I/O
472 PPIs will manage multiple block devices, PPIs that
473 want to talk to a single device must specify the device
474 index that was assigned during the enumeration process.
475 This index is a number from one to NumberBlockDevices.
476 @param[in] StartLBA The starting logical block address (LBA) to read from
478 @param[in] BufferSize The size of the Buffer in bytes. This number must be
479 a multiple of the intrinsic block size of the device.
480 @param[out] Buffer A pointer to the destination buffer for the data.
481 The caller is responsible for the ownership of the
484 @retval EFI_SUCCESS The data was read correctly from the device.
485 @retval EFI_DEVICE_ERROR The device reported an error while attempting
486 to perform the read operation.
487 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
488 valid, or the buffer is not properly aligned.
489 @retval EFI_NO_MEDIA There is no media in the device.
490 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
491 the intrinsic block size of the device.
496 AhciBlockIoReadBlocks2 (
497 IN EFI_PEI_SERVICES
**PeiServices
,
498 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI
*This
,
499 IN UINTN DeviceIndex
,
500 IN EFI_PEI_LBA StartLBA
,
505 PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
;
508 return EFI_INVALID_PARAMETER
;
511 Private
= GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2 (This
);
512 return AhciBlockIoReadBlocks (