]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Ata/AhciPei/AhciPeiBlockIo.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Bus / Ata / AhciPei / AhciPeiBlockIo.c
1 /** @file
2 The AhciPei driver is used to manage ATA hard disk device working under AHCI
3 mode at PEI phase.
4
5 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include "AhciPei.h"
12
13 /**
14 Traverse the attached ATA devices list to find out the device with given index.
15
16 @param[in] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA
17 instance.
18 @param[in] DeviceIndex The device index.
19
20 @retval The pointer to the PEI_AHCI_ATA_DEVICE_DATA structure of the device
21 info to access.
22
23 **/
24 PEI_AHCI_ATA_DEVICE_DATA *
25 SearchDeviceByIndex (
26 IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private,
27 IN UINTN DeviceIndex
28 )
29 {
30 PEI_AHCI_ATA_DEVICE_DATA *DeviceData;
31 LIST_ENTRY *Node;
32
33 if ((DeviceIndex == 0) || (DeviceIndex > Private->ActiveDevices)) {
34 return NULL;
35 }
36
37 Node = GetFirstNode (&Private->DeviceList);
38 while (!IsNull (&Private->DeviceList, Node)) {
39 DeviceData = AHCI_PEI_ATA_DEVICE_INFO_FROM_THIS (Node);
40
41 if (DeviceData->DeviceIndex == DeviceIndex) {
42 return DeviceData;
43 }
44
45 Node = GetNextNode (&Private->DeviceList, Node);
46 }
47
48 return NULL;
49 }
50
51 /**
52 Read a number of blocks from ATA device.
53
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.
56
57 @param[in] DeviceData The pointer to the PEI_AHCI_ATA_DEVICE_DATA
58 data structure.
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.
62
63 @retval EFI_SUCCESS The data transfer is complete successfully.
64 @return Others Some error occurs when transferring data.
65
66 **/
67 EFI_STATUS
68 AccessAtaDevice (
69 IN PEI_AHCI_ATA_DEVICE_DATA *DeviceData,
70 IN OUT UINT8 *Buffer,
71 IN EFI_LBA StartLba,
72 IN UINTN NumberOfBlocks
73 )
74 {
75 EFI_STATUS Status;
76 UINTN MaxTransferBlockNumber;
77 UINTN TransferBlockNumber;
78 UINTN BlockSize;
79
80 //
81 // Ensure Lba48Bit is a valid boolean value
82 //
83 ASSERT ((UINTN)DeviceData->Lba48Bit < 2);
84 if ((UINTN)DeviceData->Lba48Bit >= 2) {
85 return EFI_INVALID_PARAMETER;
86 }
87
88 Status = EFI_SUCCESS;
89 MaxTransferBlockNumber = mMaxTransferBlockNumber[DeviceData->Lba48Bit];
90 BlockSize = DeviceData->Media.BlockSize;
91
92 do {
93 if (NumberOfBlocks > MaxTransferBlockNumber) {
94 TransferBlockNumber = MaxTransferBlockNumber;
95 NumberOfBlocks -= MaxTransferBlockNumber;
96 } else {
97 TransferBlockNumber = NumberOfBlocks;
98 NumberOfBlocks = 0;
99 }
100
101 DEBUG ((
102 DEBUG_BLKIO,
103 "%a: Blocking AccessAtaDevice, TransferBlockNumber = %x; StartLba = %x\n",
104 __FUNCTION__,
105 TransferBlockNumber,
106 StartLba
107 ));
108
109 Status = TransferAtaDevice (
110 DeviceData,
111 Buffer,
112 StartLba,
113 (UINT32)TransferBlockNumber,
114 FALSE // Read
115 );
116 if (EFI_ERROR (Status)) {
117 return Status;
118 }
119
120 StartLba += TransferBlockNumber;
121 Buffer += TransferBlockNumber * BlockSize;
122 } while (NumberOfBlocks > 0);
123
124 return Status;
125 }
126
127 /**
128 Read specified bytes from Lba from the device.
129
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.
134
135 @retval EFI_SUCCESS Data are read from the device.
136 @retval Others Fail to read all the data.
137
138 **/
139 EFI_STATUS
140 AhciRead (
141 IN PEI_AHCI_ATA_DEVICE_DATA *DeviceData,
142 OUT VOID *Buffer,
143 IN EFI_LBA StartLba,
144 IN UINTN BufferSize
145 )
146 {
147 EFI_STATUS Status;
148 UINTN BlockSize;
149 UINTN NumberOfBlocks;
150
151 //
152 // Check parameters.
153 //
154 if (Buffer == NULL) {
155 return EFI_INVALID_PARAMETER;
156 }
157
158 if (BufferSize == 0) {
159 return EFI_SUCCESS;
160 }
161
162 BlockSize = DeviceData->Media.BlockSize;
163 if ((BufferSize % BlockSize) != 0) {
164 return EFI_BAD_BUFFER_SIZE;
165 }
166
167 if (StartLba > DeviceData->Media.LastBlock) {
168 return EFI_INVALID_PARAMETER;
169 }
170
171 NumberOfBlocks = BufferSize / BlockSize;
172 if (NumberOfBlocks - 1 > DeviceData->Media.LastBlock - StartLba) {
173 return EFI_INVALID_PARAMETER;
174 }
175
176 //
177 // Invoke low level AtaDevice Access Routine.
178 //
179 Status = AccessAtaDevice (DeviceData, Buffer, StartLba, NumberOfBlocks);
180
181 return Status;
182 }
183
184 /**
185 Gets the count of block I/O devices that one specific block driver detects.
186
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
189 will return zero.
190
191 @param[in] PeiServices General-purpose services that are available
192 to every PEIM.
193 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
194 instance.
195 @param[out] NumberBlockDevices The number of block I/O devices discovered.
196
197 @retval EFI_SUCCESS The operation performed successfully.
198
199 **/
200 EFI_STATUS
201 EFIAPI
202 AhciBlockIoGetDeviceNo (
203 IN EFI_PEI_SERVICES **PeiServices,
204 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
205 OUT UINTN *NumberBlockDevices
206 )
207 {
208 PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private;
209
210 if ((This == NULL) || (NumberBlockDevices == NULL)) {
211 return EFI_INVALID_PARAMETER;
212 }
213
214 Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO (This);
215 *NumberBlockDevices = Private->ActiveDevices;
216
217 return EFI_SUCCESS;
218 }
219
220 /**
221 Gets a block device's media information.
222
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.
226
227 @param[in] PeiServices General-purpose services that are available to every
228 PEIM
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
236 NumberBlockDevices.
237 @param[out] MediaInfo The media information of the specified block media.
238 The caller is responsible for the ownership of this
239 data structure.
240
241 @par Note:
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.
254
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
258 error.
259
260 **/
261 EFI_STATUS
262 EFIAPI
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
268 )
269 {
270 PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private;
271 PEI_AHCI_ATA_DEVICE_DATA *DeviceData;
272
273 if ((This == NULL) || (MediaInfo == NULL)) {
274 return EFI_INVALID_PARAMETER;
275 }
276
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;
281 }
282
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;
287
288 return EFI_SUCCESS;
289 }
290
291 /**
292 Reads the requested number of blocks from the specified block device.
293
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.
297
298 @param[in] PeiServices General-purpose services that are available to
299 every PEIM.
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
308 on the device
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
313 buffer.
314
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.
323
324 **/
325 EFI_STATUS
326 EFIAPI
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,
332 IN UINTN BufferSize,
333 OUT VOID *Buffer
334 )
335 {
336 PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private;
337 PEI_AHCI_ATA_DEVICE_DATA *DeviceData;
338
339 if (This == NULL) {
340 return EFI_INVALID_PARAMETER;
341 }
342
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;
347 }
348
349 return AhciRead (DeviceData, Buffer, StartLBA, BufferSize);
350 }
351
352 /**
353 Gets the count of block I/O devices that one specific block driver detects.
354
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
357 will return zero.
358
359 @param[in] PeiServices General-purpose services that are available
360 to every PEIM.
361 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI
362 instance.
363 @param[out] NumberBlockDevices The number of block I/O devices discovered.
364
365 @retval EFI_SUCCESS The operation performed successfully.
366
367 **/
368 EFI_STATUS
369 EFIAPI
370 AhciBlockIoGetDeviceNo2 (
371 IN EFI_PEI_SERVICES **PeiServices,
372 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
373 OUT UINTN *NumberBlockDevices
374 )
375 {
376 PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private;
377
378 if ((This == NULL) || (NumberBlockDevices == NULL)) {
379 return EFI_INVALID_PARAMETER;
380 }
381
382 Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2 (This);
383 *NumberBlockDevices = Private->ActiveDevices;
384
385 return EFI_SUCCESS;
386 }
387
388 /**
389 Gets a block device's media information.
390
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.
394
395 @param[in] PeiServices General-purpose services that are available to every
396 PEIM
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
404 NumberBlockDevices.
405 @param[out] MediaInfo The media information of the specified block media.
406 The caller is responsible for the ownership of this
407 data structure.
408
409 @par Note:
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.
422
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
426 error.
427
428 **/
429 EFI_STATUS
430 EFIAPI
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
436 )
437 {
438 PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private;
439 PEI_AHCI_ATA_DEVICE_DATA *DeviceData;
440
441 if ((This == NULL) || (MediaInfo == NULL)) {
442 return EFI_INVALID_PARAMETER;
443 }
444
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;
449 }
450
451 CopyMem (
452 MediaInfo,
453 &DeviceData->Media,
454 sizeof (EFI_PEI_BLOCK_IO2_MEDIA)
455 );
456
457 return EFI_SUCCESS;
458 }
459
460 /**
461 Reads the requested number of blocks from the specified block device.
462
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.
466
467 @param[in] PeiServices General-purpose services that are available to
468 every PEIM.
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
477 on the device
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
482 buffer.
483
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.
492
493 **/
494 EFI_STATUS
495 EFIAPI
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,
501 IN UINTN BufferSize,
502 OUT VOID *Buffer
503 )
504 {
505 PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private;
506
507 if (This == NULL) {
508 return EFI_INVALID_PARAMETER;
509 }
510
511 Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2 (This);
512 return AhciBlockIoReadBlocks (
513 PeiServices,
514 &Private->BlkIoPpi,
515 DeviceIndex,
516 StartLBA,
517 BufferSize,
518 Buffer
519 );
520 }