2 The helper functions for BlockIo and BlockIo2 protocol.
4 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 Nonblocking I/O callback function when the event is signaled.
14 @param[in] Event The Event this notify function registered to.
15 @param[in] Context Pointer to the context data registered to the
28 gBS
->CloseEvent (Event
);
30 Request
= (SD_REQUEST
*)Context
;
35 "Sd Async Request: CmdIndex[%d] Arg[%08x] %r\n",
36 Request
->SdMmcCmdBlk
.CommandIndex
,
37 Request
->SdMmcCmdBlk
.CommandArgument
,
38 Request
->Packet
.TransactionStatus
42 if (EFI_ERROR (Request
->Packet
.TransactionStatus
)) {
43 Request
->Token
->TransactionStatus
= Request
->Packet
.TransactionStatus
;
46 RemoveEntryList (&Request
->Link
);
49 gBS
->SignalEvent (Request
->Token
->Event
);
56 Send command SET_RELATIVE_ADDRESS to the device to set the device address.
58 @param[in] Device A pointer to the SD_DEVICE instance.
59 @param[out] Rca The relative device address to assign.
61 @retval EFI_SUCCESS The request is executed successfully.
62 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
63 @retval Others The request could not be executed successfully.
73 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
74 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
75 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
76 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
78 PassThru
= Device
->Private
->PassThru
;
80 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
81 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
82 ZeroMem (&Packet
, sizeof (Packet
));
83 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
84 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
85 Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
87 SdMmcCmdBlk
.CommandIndex
= SD_SET_RELATIVE_ADDR
;
88 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeBcr
;
89 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR6
;
91 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &Packet
, NULL
);
92 if (!EFI_ERROR (Status
)) {
93 DEBUG ((DEBUG_INFO
, "Set RCA succeeds with Resp0 = 0x%x\n", SdMmcStatusBlk
.Resp0
));
94 *Rca
= (UINT16
)(SdMmcStatusBlk
.Resp0
>> 16);
101 Send command SELECT to the device to select/deselect the device.
103 @param[in] Device A pointer to the SD_DEVICE instance.
104 @param[in] Rca The relative device address to use.
106 @retval EFI_SUCCESS The request is executed successfully.
107 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
108 @retval Others The request could not be executed successfully.
113 IN SD_DEVICE
*Device
,
118 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
119 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
120 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
121 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
123 PassThru
= Device
->Private
->PassThru
;
125 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
126 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
127 ZeroMem (&Packet
, sizeof (Packet
));
128 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
129 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
130 Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
132 SdMmcCmdBlk
.CommandIndex
= SD_SELECT_DESELECT_CARD
;
133 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
135 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1b
;
138 SdMmcCmdBlk
.CommandArgument
= (UINT32
)Rca
<< 16;
140 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &Packet
, NULL
);
146 Send command SEND_STATUS to the device to get device status.
148 @param[in] Device A pointer to the SD_DEVICE instance.
149 @param[in] Rca The relative device address to use.
150 @param[out] DevStatus The buffer to store the device status.
152 @retval EFI_SUCCESS The request is executed successfully.
153 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
154 @retval Others The request could not be executed successfully.
159 IN SD_DEVICE
*Device
,
161 OUT UINT32
*DevStatus
165 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
166 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
167 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
168 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
170 PassThru
= Device
->Private
->PassThru
;
172 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
173 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
174 ZeroMem (&Packet
, sizeof (Packet
));
175 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
176 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
177 Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
179 SdMmcCmdBlk
.CommandIndex
= SD_SEND_STATUS
;
180 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
181 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
182 SdMmcCmdBlk
.CommandArgument
= (UINT32
)Rca
<< 16;
184 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &Packet
, NULL
);
185 if (!EFI_ERROR (Status
)) {
186 CopyMem (DevStatus
, &SdMmcStatusBlk
.Resp0
, sizeof (UINT32
));
193 Send command SEND_CSD to the device to get the CSD register data.
195 @param[in] Device A pointer to the SD_DEVICE instance.
196 @param[in] Rca The relative device address to use.
197 @param[out] Csd The buffer to store the SD_CSD register data.
199 @retval EFI_SUCCESS The request is executed successfully.
200 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
201 @retval Others The request could not be executed successfully.
206 IN SD_DEVICE
*Device
,
212 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
213 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
214 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
215 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
217 PassThru
= Device
->Private
->PassThru
;
219 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
220 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
221 ZeroMem (&Packet
, sizeof (Packet
));
222 ZeroMem (Csd
, sizeof (SD_CSD
));
224 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
225 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
226 Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
228 SdMmcCmdBlk
.CommandIndex
= SD_SEND_CSD
;
229 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
230 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR2
;
231 SdMmcCmdBlk
.CommandArgument
= (UINT32
)Rca
<< 16;
233 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &Packet
, NULL
);
235 if (!EFI_ERROR (Status
)) {
237 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
239 CopyMem (((UINT8
*)Csd
) + 1, &SdMmcStatusBlk
.Resp0
, sizeof (SD_CSD
) - 1);
246 Send command SEND_CID to the device to get the CID register data.
248 @param[in] Device A pointer to the SD_DEVICE instance.
249 @param[in] Rca The relative device address to use.
250 @param[out] Cid The buffer to store the SD_CID register data.
252 @retval EFI_SUCCESS The request is executed successfully.
253 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
254 @retval Others The request could not be executed successfully.
259 IN SD_DEVICE
*Device
,
265 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
266 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
267 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
268 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
270 PassThru
= Device
->Private
->PassThru
;
272 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
273 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
274 ZeroMem (&Packet
, sizeof (Packet
));
275 ZeroMem (Cid
, sizeof (SD_CID
));
277 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
278 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
279 Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
281 SdMmcCmdBlk
.CommandIndex
= SD_SEND_CID
;
282 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
283 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR2
;
284 SdMmcCmdBlk
.CommandArgument
= (UINT32
)Rca
<< 16;
286 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &Packet
, NULL
);
288 if (!EFI_ERROR (Status
)) {
290 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
292 CopyMem (((UINT8
*)Cid
) + 1, &SdMmcStatusBlk
.Resp0
, sizeof (SD_CID
) - 1);
299 Read/write single block through sync or async I/O request.
301 @param[in] Device A pointer to the SD_DEVICE instance.
302 @param[in] Lba The starting logical block address to be read/written.
303 The caller is responsible for reading/writing to only
304 legitimate locations.
305 @param[in] Buffer A pointer to the destination/source buffer for the data.
306 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
307 @param[in] IsRead Indicates it is a read or write operation.
308 @param[in] Token A pointer to the token associated with the transaction.
309 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
310 This parameter is only meaningful in async I/O request.
312 @retval EFI_SUCCESS The request is executed successfully.
313 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
314 @retval Others The request could not be executed successfully.
319 IN SD_DEVICE
*Device
,
324 IN EFI_BLOCK_IO2_TOKEN
*Token
,
329 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
330 SD_REQUEST
*RwSingleBlkReq
;
333 RwSingleBlkReq
= NULL
;
334 PassThru
= Device
->Private
->PassThru
;
336 RwSingleBlkReq
= AllocateZeroPool (sizeof (SD_REQUEST
));
337 if (RwSingleBlkReq
== NULL
) {
338 Status
= EFI_OUT_OF_RESOURCES
;
342 RwSingleBlkReq
->Signature
= SD_REQUEST_SIGNATURE
;
343 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
344 InsertTailList (&Device
->Queue
, &RwSingleBlkReq
->Link
);
345 gBS
->RestoreTPL (OldTpl
);
346 RwSingleBlkReq
->Packet
.SdMmcCmdBlk
= &RwSingleBlkReq
->SdMmcCmdBlk
;
347 RwSingleBlkReq
->Packet
.SdMmcStatusBlk
= &RwSingleBlkReq
->SdMmcStatusBlk
;
349 // Calculate timeout value through the below formula.
350 // Timeout = (transfer size) / (2MB/s).
351 // Taking 2MB/s as divisor as it's the lowest transfer speed
353 // Refer to SD Physical Layer Simplified spec section 3.4 for details.
355 RwSingleBlkReq
->Packet
.Timeout
= (BufferSize
/ (2 * 1024 * 1024) + 1) * 1000 * 1000;
358 RwSingleBlkReq
->Packet
.InDataBuffer
= Buffer
;
359 RwSingleBlkReq
->Packet
.InTransferLength
= (UINT32
)BufferSize
;
361 RwSingleBlkReq
->SdMmcCmdBlk
.CommandIndex
= SD_READ_SINGLE_BLOCK
;
362 RwSingleBlkReq
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAdtc
;
363 RwSingleBlkReq
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
365 RwSingleBlkReq
->Packet
.OutDataBuffer
= Buffer
;
366 RwSingleBlkReq
->Packet
.OutTransferLength
= (UINT32
)BufferSize
;
368 RwSingleBlkReq
->SdMmcCmdBlk
.CommandIndex
= SD_WRITE_SINGLE_BLOCK
;
369 RwSingleBlkReq
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAdtc
;
370 RwSingleBlkReq
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
373 if (Device
->SectorAddressing
) {
374 RwSingleBlkReq
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)Lba
;
376 RwSingleBlkReq
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)MultU64x32 (Lba
, Device
->BlockMedia
.BlockSize
);
379 RwSingleBlkReq
->IsEnd
= IsEnd
;
380 RwSingleBlkReq
->Token
= Token
;
382 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
383 Status
= gBS
->CreateEvent (
388 &RwSingleBlkReq
->Event
390 if (EFI_ERROR (Status
)) {
394 RwSingleBlkReq
->Event
= NULL
;
397 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &RwSingleBlkReq
->Packet
, RwSingleBlkReq
->Event
);
400 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
402 // For asynchronous operation, only free request and event in error case.
403 // The request and event will be freed in asynchronous callback for success case.
405 if (EFI_ERROR (Status
) && (RwSingleBlkReq
!= NULL
)) {
406 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
407 RemoveEntryList (&RwSingleBlkReq
->Link
);
408 gBS
->RestoreTPL (OldTpl
);
409 if (RwSingleBlkReq
->Event
!= NULL
) {
410 gBS
->CloseEvent (RwSingleBlkReq
->Event
);
413 FreePool (RwSingleBlkReq
);
417 // For synchronous operation, free request whatever the execution result is.
419 if (RwSingleBlkReq
!= NULL
) {
420 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
421 RemoveEntryList (&RwSingleBlkReq
->Link
);
422 gBS
->RestoreTPL (OldTpl
);
423 FreePool (RwSingleBlkReq
);
431 Read/write multiple blocks through sync or async I/O request.
433 @param[in] Device A pointer to the SD_DEVICE instance.
434 @param[in] Lba The starting logical block address to be read/written.
435 The caller is responsible for reading/writing to only
436 legitimate locations.
437 @param[in] Buffer A pointer to the destination/source buffer for the data.
438 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
439 @param[in] IsRead Indicates it is a read or write operation.
440 @param[in] Token A pointer to the token associated with the transaction.
441 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
442 This parameter is only meaningful in async I/O request.
444 @retval EFI_SUCCESS The request is executed successfully.
445 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
446 @retval Others The request could not be executed successfully.
451 IN SD_DEVICE
*Device
,
456 IN EFI_BLOCK_IO2_TOKEN
*Token
,
461 SD_REQUEST
*RwMultiBlkReq
;
462 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
465 RwMultiBlkReq
= NULL
;
467 PassThru
= Device
->Private
->PassThru
;
469 RwMultiBlkReq
= AllocateZeroPool (sizeof (SD_REQUEST
));
470 if (RwMultiBlkReq
== NULL
) {
471 Status
= EFI_OUT_OF_RESOURCES
;
475 RwMultiBlkReq
->Signature
= SD_REQUEST_SIGNATURE
;
476 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
477 InsertTailList (&Device
->Queue
, &RwMultiBlkReq
->Link
);
478 gBS
->RestoreTPL (OldTpl
);
479 RwMultiBlkReq
->Packet
.SdMmcCmdBlk
= &RwMultiBlkReq
->SdMmcCmdBlk
;
480 RwMultiBlkReq
->Packet
.SdMmcStatusBlk
= &RwMultiBlkReq
->SdMmcStatusBlk
;
482 // Calculate timeout value through the below formula.
483 // Timeout = (transfer size) / (2MB/s).
484 // Taking 2MB/s as divisor as it's the lowest transfer speed
486 // Refer to SD Physical Layer Simplified spec section 3.4 for details.
488 RwMultiBlkReq
->Packet
.Timeout
= (BufferSize
/ (2 * 1024 * 1024) + 1) * 1000 * 1000;
491 RwMultiBlkReq
->Packet
.InDataBuffer
= Buffer
;
492 RwMultiBlkReq
->Packet
.InTransferLength
= (UINT32
)BufferSize
;
494 RwMultiBlkReq
->SdMmcCmdBlk
.CommandIndex
= SD_READ_MULTIPLE_BLOCK
;
495 RwMultiBlkReq
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAdtc
;
496 RwMultiBlkReq
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
498 RwMultiBlkReq
->Packet
.OutDataBuffer
= Buffer
;
499 RwMultiBlkReq
->Packet
.OutTransferLength
= (UINT32
)BufferSize
;
501 RwMultiBlkReq
->SdMmcCmdBlk
.CommandIndex
= SD_WRITE_MULTIPLE_BLOCK
;
502 RwMultiBlkReq
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAdtc
;
503 RwMultiBlkReq
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
506 if (Device
->SectorAddressing
) {
507 RwMultiBlkReq
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)Lba
;
509 RwMultiBlkReq
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)MultU64x32 (Lba
, Device
->BlockMedia
.BlockSize
);
512 RwMultiBlkReq
->IsEnd
= IsEnd
;
513 RwMultiBlkReq
->Token
= Token
;
515 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
516 Status
= gBS
->CreateEvent (
521 &RwMultiBlkReq
->Event
523 if (EFI_ERROR (Status
)) {
527 RwMultiBlkReq
->Event
= NULL
;
530 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &RwMultiBlkReq
->Packet
, RwMultiBlkReq
->Event
);
533 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
535 // For asynchronous operation, only free request and event in error case.
536 // The request and event will be freed in asynchronous callback for success case.
538 if (EFI_ERROR (Status
) && (RwMultiBlkReq
!= NULL
)) {
539 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
540 RemoveEntryList (&RwMultiBlkReq
->Link
);
541 gBS
->RestoreTPL (OldTpl
);
542 if (RwMultiBlkReq
->Event
!= NULL
) {
543 gBS
->CloseEvent (RwMultiBlkReq
->Event
);
546 FreePool (RwMultiBlkReq
);
550 // For synchronous operation, free request whatever the execution result is.
552 if (RwMultiBlkReq
!= NULL
) {
553 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
554 RemoveEntryList (&RwMultiBlkReq
->Link
);
555 gBS
->RestoreTPL (OldTpl
);
556 FreePool (RwMultiBlkReq
);
564 This function transfers data from/to the sd memory card device.
566 @param[in] Device A pointer to the SD_DEVICE instance.
567 @param[in] MediaId The media ID that the read/write request is for.
568 @param[in] Lba The starting logical block address to be read/written.
569 The caller is responsible for reading/writing to only
570 legitimate locations.
571 @param[in, out] Buffer A pointer to the destination/source buffer for the data.
572 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
573 @param[in] IsRead Indicates it is a read or write operation.
574 @param[in, out] Token A pointer to the token associated with the transaction.
576 @retval EFI_SUCCESS The data was read/written correctly to the device.
577 @retval EFI_WRITE_PROTECTED The device can not be read/written to.
578 @retval EFI_DEVICE_ERROR The device reported an error while performing the read/write.
579 @retval EFI_NO_MEDIA There is no media in the device.
580 @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.
581 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
582 @retval EFI_INVALID_PARAMETER The read/write request contains LBAs that are not valid,
583 or the buffer is not on proper alignment.
588 IN SD_DEVICE
*Device
,
594 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
598 EFI_BLOCK_IO_MEDIA
*Media
;
606 Status
= EFI_SUCCESS
;
607 Media
= &Device
->BlockMedia
;
610 if (MediaId
!= Media
->MediaId
) {
611 return EFI_MEDIA_CHANGED
;
614 if (!IsRead
&& Media
->ReadOnly
) {
615 return EFI_WRITE_PROTECTED
;
621 if (Buffer
== NULL
) {
622 return EFI_INVALID_PARAMETER
;
625 if (BufferSize
== 0) {
626 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
627 Token
->TransactionStatus
= EFI_SUCCESS
;
628 gBS
->SignalEvent (Token
->Event
);
634 BlockSize
= Media
->BlockSize
;
635 if ((BufferSize
% BlockSize
) != 0) {
636 return EFI_BAD_BUFFER_SIZE
;
639 BlockNum
= BufferSize
/ BlockSize
;
640 if ((Lba
+ BlockNum
- 1) > Media
->LastBlock
) {
641 return EFI_INVALID_PARAMETER
;
644 IoAlign
= Media
->IoAlign
;
645 if ((IoAlign
> 0) && (((UINTN
)Buffer
& (IoAlign
- 1)) != 0)) {
646 return EFI_INVALID_PARAMETER
;
649 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
650 Token
->TransactionStatus
= EFI_SUCCESS
;
654 // Start to execute data transfer. The max block number in single cmd is 65535 blocks.
656 Remaining
= BlockNum
;
659 while (Remaining
> 0) {
660 if (Remaining
<= MaxBlock
) {
661 BlockNum
= Remaining
;
667 BufferSize
= BlockNum
* BlockSize
;
669 Status
= SdRwSingleBlock (Device
, Lba
, Buffer
, BufferSize
, IsRead
, Token
, LastRw
);
671 Status
= SdRwMultiBlocks (Device
, Lba
, Buffer
, BufferSize
, IsRead
, Token
, LastRw
);
674 if (EFI_ERROR (Status
)) {
680 "Sd%a(): Lba 0x%x BlkNo 0x%x Event %p with %r\n",
681 IsRead
? "Read" : "Write",
684 (Token
!= NULL
) ? Token
->Event
: NULL
,
688 Buffer
= (UINT8
*)Buffer
+ BufferSize
;
689 Remaining
-= BlockNum
;
696 Reset the Block Device.
698 @param This Indicates a pointer to the calling context.
699 @param ExtendedVerification Driver may perform diagnostics on reset.
701 @retval EFI_SUCCESS The device was reset.
702 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
709 IN EFI_BLOCK_IO_PROTOCOL
*This
,
710 IN BOOLEAN ExtendedVerification
715 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
717 Device
= SD_DEVICE_DATA_FROM_BLKIO (This
);
719 PassThru
= Device
->Private
->PassThru
;
720 Status
= PassThru
->ResetDevice (PassThru
, Device
->Slot
);
721 if (EFI_ERROR (Status
)) {
722 Status
= EFI_DEVICE_ERROR
;
729 Read BufferSize bytes from Lba into Buffer.
731 @param This Indicates a pointer to the calling context.
732 @param MediaId Id of the media, changes every time the media is replaced.
733 @param Lba The starting Logical Block Address to read from
734 @param BufferSize Size of Buffer, must be a multiple of device block size.
735 @param Buffer A pointer to the destination buffer for the data. The caller is
736 responsible for either having implicit or explicit ownership of the buffer.
738 @retval EFI_SUCCESS The data was read correctly from the device.
739 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
740 @retval EFI_NO_MEDIA There is no media in the device.
741 @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.
742 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
743 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
744 or the buffer is not on proper alignment.
750 IN EFI_BLOCK_IO_PROTOCOL
*This
,
760 Device
= SD_DEVICE_DATA_FROM_BLKIO (This
);
762 Status
= SdReadWrite (Device
, MediaId
, Lba
, Buffer
, BufferSize
, TRUE
, NULL
);
767 Write BufferSize bytes from Lba into Buffer.
769 @param This Indicates a pointer to the calling context.
770 @param MediaId The media ID that the write request is for.
771 @param Lba The starting logical block address to be written. The caller is
772 responsible for writing to only legitimate locations.
773 @param BufferSize Size of Buffer, must be a multiple of device block size.
774 @param Buffer A pointer to the source buffer for the data.
776 @retval EFI_SUCCESS The data was written correctly to the device.
777 @retval EFI_WRITE_PROTECTED The device can not be written to.
778 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
779 @retval EFI_NO_MEDIA There is no media in the device.
780 @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.
781 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
782 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
783 or the buffer is not on proper alignment.
789 IN EFI_BLOCK_IO_PROTOCOL
*This
,
799 Device
= SD_DEVICE_DATA_FROM_BLKIO (This
);
801 Status
= SdReadWrite (Device
, MediaId
, Lba
, Buffer
, BufferSize
, FALSE
, NULL
);
806 Flush the Block Device.
808 @param This Indicates a pointer to the calling context.
810 @retval EFI_SUCCESS All outstanding data was written to the device
811 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data
812 @retval EFI_NO_MEDIA There is no media in the device.
818 IN EFI_BLOCK_IO_PROTOCOL
*This
828 Reset the Block Device.
830 @param[in] This Indicates a pointer to the calling context.
831 @param[in] ExtendedVerification Driver may perform diagnostics on reset.
833 @retval EFI_SUCCESS The device was reset.
834 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
841 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
842 IN BOOLEAN ExtendedVerification
847 LIST_ENTRY
*NextLink
;
851 Device
= SD_DEVICE_DATA_FROM_BLKIO2 (This
);
853 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
854 for (Link
= GetFirstNode (&Device
->Queue
);
855 !IsNull (&Device
->Queue
, Link
);
858 NextLink
= GetNextNode (&Device
->Queue
, Link
);
859 RemoveEntryList (Link
);
861 Request
= SD_REQUEST_FROM_LINK (Link
);
863 gBS
->CloseEvent (Request
->Event
);
864 Request
->Token
->TransactionStatus
= EFI_ABORTED
;
866 if (Request
->IsEnd
) {
867 gBS
->SignalEvent (Request
->Token
->Event
);
873 gBS
->RestoreTPL (OldTpl
);
879 Read BufferSize bytes from Lba into Buffer.
881 @param[in] This Indicates a pointer to the calling context.
882 @param[in] MediaId Id of the media, changes every time the media is replaced.
883 @param[in] Lba The starting Logical Block Address to read from.
884 @param[in, out] Token A pointer to the token associated with the transaction.
885 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
886 @param[out] Buffer A pointer to the destination buffer for the data. The caller is
887 responsible for either having implicit or explicit ownership of the buffer.
889 @retval EFI_SUCCESS The read request was queued if Event is not NULL.
890 The data was read correctly from the device if
892 @retval EFI_DEVICE_ERROR The device reported an error while performing
894 @retval EFI_NO_MEDIA There is no media in the device.
895 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
896 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the
897 intrinsic block size of the device.
898 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
899 or the buffer is not on proper alignment.
900 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
907 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
910 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
918 Device
= SD_DEVICE_DATA_FROM_BLKIO2 (This
);
920 Status
= SdReadWrite (Device
, MediaId
, Lba
, Buffer
, BufferSize
, TRUE
, Token
);
925 Write BufferSize bytes from Lba into Buffer.
927 @param[in] This Indicates a pointer to the calling context.
928 @param[in] MediaId The media ID that the write request is for.
929 @param[in] Lba The starting logical block address to be written. The
930 caller is responsible for writing to only legitimate
932 @param[in, out] Token A pointer to the token associated with the transaction.
933 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
934 @param[in] Buffer A pointer to the source buffer for the data.
936 @retval EFI_SUCCESS The data was written correctly to the device.
937 @retval EFI_WRITE_PROTECTED The device can not be written to.
938 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
939 @retval EFI_NO_MEDIA There is no media in the device.
940 @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.
941 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
942 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
943 or the buffer is not on proper alignment.
949 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
952 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
960 Device
= SD_DEVICE_DATA_FROM_BLKIO2 (This
);
962 Status
= SdReadWrite (Device
, MediaId
, Lba
, Buffer
, BufferSize
, FALSE
, Token
);
967 Flush the Block Device.
969 @param[in] This Indicates a pointer to the calling context.
970 @param[in, out] Token A pointer to the token associated with the transaction.
972 @retval EFI_SUCCESS All outstanding data was written to the device
973 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data
974 @retval EFI_NO_MEDIA There is no media in the device.
980 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
981 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
985 // Signal event and return directly.
987 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
988 Token
->TransactionStatus
= EFI_SUCCESS
;
989 gBS
->SignalEvent (Token
->Event
);
996 Set the erase start address through sync or async I/O request.
998 @param[in] Device A pointer to the SD_DEVICE instance.
999 @param[in] StartLba The starting logical block address to be erased.
1000 @param[in] Token A pointer to the token associated with the transaction.
1001 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
1002 This parameter is only meaningful in async I/O request.
1004 @retval EFI_SUCCESS The request is executed successfully.
1005 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
1006 @retval Others The request could not be executed successfully.
1011 IN SD_DEVICE
*Device
,
1012 IN EFI_LBA StartLba
,
1013 IN EFI_BLOCK_IO2_TOKEN
*Token
,
1018 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
1019 SD_REQUEST
*EraseBlockStart
;
1022 EraseBlockStart
= NULL
;
1023 PassThru
= Device
->Private
->PassThru
;
1025 EraseBlockStart
= AllocateZeroPool (sizeof (SD_REQUEST
));
1026 if (EraseBlockStart
== NULL
) {
1027 Status
= EFI_OUT_OF_RESOURCES
;
1031 EraseBlockStart
->Signature
= SD_REQUEST_SIGNATURE
;
1032 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1033 InsertTailList (&Device
->Queue
, &EraseBlockStart
->Link
);
1034 gBS
->RestoreTPL (OldTpl
);
1035 EraseBlockStart
->Packet
.SdMmcCmdBlk
= &EraseBlockStart
->SdMmcCmdBlk
;
1036 EraseBlockStart
->Packet
.SdMmcStatusBlk
= &EraseBlockStart
->SdMmcStatusBlk
;
1037 EraseBlockStart
->Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
1039 EraseBlockStart
->SdMmcCmdBlk
.CommandIndex
= SD_ERASE_WR_BLK_START
;
1040 EraseBlockStart
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
1041 EraseBlockStart
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
1043 if (Device
->SectorAddressing
) {
1044 EraseBlockStart
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)StartLba
;
1046 EraseBlockStart
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)MultU64x32 (StartLba
, Device
->BlockMedia
.BlockSize
);
1049 EraseBlockStart
->IsEnd
= IsEnd
;
1050 EraseBlockStart
->Token
= Token
;
1052 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1053 Status
= gBS
->CreateEvent (
1058 &EraseBlockStart
->Event
1060 if (EFI_ERROR (Status
)) {
1064 EraseBlockStart
->Event
= NULL
;
1067 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &EraseBlockStart
->Packet
, EraseBlockStart
->Event
);
1070 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1072 // For asynchronous operation, only free request and event in error case.
1073 // The request and event will be freed in asynchronous callback for success case.
1075 if (EFI_ERROR (Status
) && (EraseBlockStart
!= NULL
)) {
1076 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1077 RemoveEntryList (&EraseBlockStart
->Link
);
1078 gBS
->RestoreTPL (OldTpl
);
1079 if (EraseBlockStart
->Event
!= NULL
) {
1080 gBS
->CloseEvent (EraseBlockStart
->Event
);
1083 FreePool (EraseBlockStart
);
1087 // For synchronous operation, free request whatever the execution result is.
1089 if (EraseBlockStart
!= NULL
) {
1090 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1091 RemoveEntryList (&EraseBlockStart
->Link
);
1092 gBS
->RestoreTPL (OldTpl
);
1093 FreePool (EraseBlockStart
);
1101 Set the erase end address through sync or async I/O request.
1103 @param[in] Device A pointer to the SD_DEVICE instance.
1104 @param[in] EndLba The ending logical block address to be erased.
1105 @param[in] Token A pointer to the token associated with the transaction.
1106 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
1107 This parameter is only meaningful in async I/O request.
1109 @retval EFI_SUCCESS The request is executed successfully.
1110 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
1111 @retval Others The request could not be executed successfully.
1116 IN SD_DEVICE
*Device
,
1118 IN EFI_BLOCK_IO2_TOKEN
*Token
,
1123 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
1124 SD_REQUEST
*EraseBlockEnd
;
1127 EraseBlockEnd
= NULL
;
1128 PassThru
= Device
->Private
->PassThru
;
1130 EraseBlockEnd
= AllocateZeroPool (sizeof (SD_REQUEST
));
1131 if (EraseBlockEnd
== NULL
) {
1132 Status
= EFI_OUT_OF_RESOURCES
;
1136 EraseBlockEnd
->Signature
= SD_REQUEST_SIGNATURE
;
1137 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1138 InsertTailList (&Device
->Queue
, &EraseBlockEnd
->Link
);
1139 gBS
->RestoreTPL (OldTpl
);
1140 EraseBlockEnd
->Packet
.SdMmcCmdBlk
= &EraseBlockEnd
->SdMmcCmdBlk
;
1141 EraseBlockEnd
->Packet
.SdMmcStatusBlk
= &EraseBlockEnd
->SdMmcStatusBlk
;
1142 EraseBlockEnd
->Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
1144 EraseBlockEnd
->SdMmcCmdBlk
.CommandIndex
= SD_ERASE_WR_BLK_END
;
1145 EraseBlockEnd
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
1146 EraseBlockEnd
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
1148 if (Device
->SectorAddressing
) {
1149 EraseBlockEnd
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)EndLba
;
1151 EraseBlockEnd
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)MultU64x32 (EndLba
, Device
->BlockMedia
.BlockSize
);
1154 EraseBlockEnd
->IsEnd
= IsEnd
;
1155 EraseBlockEnd
->Token
= Token
;
1157 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1158 Status
= gBS
->CreateEvent (
1163 &EraseBlockEnd
->Event
1165 if (EFI_ERROR (Status
)) {
1169 EraseBlockEnd
->Event
= NULL
;
1172 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &EraseBlockEnd
->Packet
, EraseBlockEnd
->Event
);
1175 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1177 // For asynchronous operation, only free request and event in error case.
1178 // The request and event will be freed in asynchronous callback for success case.
1180 if (EFI_ERROR (Status
) && (EraseBlockEnd
!= NULL
)) {
1181 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1182 RemoveEntryList (&EraseBlockEnd
->Link
);
1183 gBS
->RestoreTPL (OldTpl
);
1184 if (EraseBlockEnd
->Event
!= NULL
) {
1185 gBS
->CloseEvent (EraseBlockEnd
->Event
);
1188 FreePool (EraseBlockEnd
);
1192 // For synchronous operation, free request whatever the execution result is.
1194 if (EraseBlockEnd
!= NULL
) {
1195 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1196 RemoveEntryList (&EraseBlockEnd
->Link
);
1197 gBS
->RestoreTPL (OldTpl
);
1198 FreePool (EraseBlockEnd
);
1206 Erase specified blocks through sync or async I/O request.
1208 @param[in] Device A pointer to the SD_DEVICE instance.
1209 @param[in] Token A pointer to the token associated with the transaction.
1210 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
1211 This parameter is only meaningful in async I/O request.
1213 @retval EFI_SUCCESS The request is executed successfully.
1214 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
1215 @retval Others The request could not be executed successfully.
1220 IN SD_DEVICE
*Device
,
1221 IN EFI_BLOCK_IO2_TOKEN
*Token
,
1226 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
1227 SD_REQUEST
*EraseBlock
;
1231 PassThru
= Device
->Private
->PassThru
;
1233 EraseBlock
= AllocateZeroPool (sizeof (SD_REQUEST
));
1234 if (EraseBlock
== NULL
) {
1235 Status
= EFI_OUT_OF_RESOURCES
;
1239 EraseBlock
->Signature
= SD_REQUEST_SIGNATURE
;
1240 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1241 InsertTailList (&Device
->Queue
, &EraseBlock
->Link
);
1242 gBS
->RestoreTPL (OldTpl
);
1243 EraseBlock
->Packet
.SdMmcCmdBlk
= &EraseBlock
->SdMmcCmdBlk
;
1244 EraseBlock
->Packet
.SdMmcStatusBlk
= &EraseBlock
->SdMmcStatusBlk
;
1245 EraseBlock
->Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
1247 EraseBlock
->SdMmcCmdBlk
.CommandIndex
= SD_ERASE
;
1248 EraseBlock
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
1249 EraseBlock
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1b
;
1251 EraseBlock
->IsEnd
= IsEnd
;
1252 EraseBlock
->Token
= Token
;
1254 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1255 Status
= gBS
->CreateEvent (
1262 if (EFI_ERROR (Status
)) {
1266 EraseBlock
->Event
= NULL
;
1269 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &EraseBlock
->Packet
, EraseBlock
->Event
);
1272 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1274 // For asynchronous operation, only free request and event in error case.
1275 // The request and event will be freed in asynchronous callback for success case.
1277 if (EFI_ERROR (Status
) && (EraseBlock
!= NULL
)) {
1278 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1279 RemoveEntryList (&EraseBlock
->Link
);
1280 gBS
->RestoreTPL (OldTpl
);
1281 if (EraseBlock
->Event
!= NULL
) {
1282 gBS
->CloseEvent (EraseBlock
->Event
);
1285 FreePool (EraseBlock
);
1289 // For synchronous operation, free request whatever the execution result is.
1291 if (EraseBlock
!= NULL
) {
1292 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1293 RemoveEntryList (&EraseBlock
->Link
);
1294 gBS
->RestoreTPL (OldTpl
);
1295 FreePool (EraseBlock
);
1303 Erase a specified number of device blocks.
1305 @param[in] This Indicates a pointer to the calling context.
1306 @param[in] MediaId The media ID that the erase request is for.
1307 @param[in] Lba The starting logical block address to be
1308 erased. The caller is responsible for erasing
1309 only legitimate locations.
1310 @param[in, out] Token A pointer to the token associated with the
1312 @param[in] Size The size in bytes to be erased. This must be
1313 a multiple of the physical block size of the
1316 @retval EFI_SUCCESS The erase request was queued if Event is not
1317 NULL. The data was erased correctly to the
1318 device if the Event is NULL.to the device.
1319 @retval EFI_WRITE_PROTECTED The device cannot be erased due to write
1321 @retval EFI_DEVICE_ERROR The device reported an error while attempting
1322 to perform the erase operation.
1323 @retval EFI_INVALID_PARAMETER The erase request contains LBAs that are not
1325 @retval EFI_NO_MEDIA There is no media in the device.
1326 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1332 IN EFI_ERASE_BLOCK_PROTOCOL
*This
,
1335 IN OUT EFI_ERASE_BLOCK_TOKEN
*Token
,
1340 EFI_BLOCK_IO_MEDIA
*Media
;
1346 Status
= EFI_SUCCESS
;
1347 Device
= SD_DEVICE_DATA_FROM_ERASEBLK (This
);
1348 Media
= &Device
->BlockMedia
;
1350 if (MediaId
!= Media
->MediaId
) {
1351 return EFI_MEDIA_CHANGED
;
1354 if (Media
->ReadOnly
) {
1355 return EFI_WRITE_PROTECTED
;
1359 // Check parameters.
1361 BlockSize
= Media
->BlockSize
;
1362 if ((Size
% BlockSize
) != 0) {
1363 return EFI_INVALID_PARAMETER
;
1366 BlockNum
= Size
/ BlockSize
;
1367 if ((Lba
+ BlockNum
- 1) > Media
->LastBlock
) {
1368 return EFI_INVALID_PARAMETER
;
1371 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1372 Token
->TransactionStatus
= EFI_SUCCESS
;
1375 LastLba
= Lba
+ BlockNum
- 1;
1377 Status
= SdEraseBlockStart (Device
, Lba
, (EFI_BLOCK_IO2_TOKEN
*)Token
, FALSE
);
1378 if (EFI_ERROR (Status
)) {
1382 Status
= SdEraseBlockEnd (Device
, LastLba
, (EFI_BLOCK_IO2_TOKEN
*)Token
, FALSE
);
1383 if (EFI_ERROR (Status
)) {
1387 Status
= SdEraseBlock (Device
, (EFI_BLOCK_IO2_TOKEN
*)Token
, TRUE
);
1388 if (EFI_ERROR (Status
)) {
1394 "SdEraseBlocks(): Lba 0x%x BlkNo 0x%x Event %p with %r\n",
1397 (Token
!= NULL
) ? Token
->Event
: NULL
,