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
;
33 DEBUG ((DEBUG_INFO
, "Sd Async Request: CmdIndex[%d] Arg[%08x] %r\n",
34 Request
->SdMmcCmdBlk
.CommandIndex
, Request
->SdMmcCmdBlk
.CommandArgument
,
35 Request
->Packet
.TransactionStatus
));
38 if (EFI_ERROR (Request
->Packet
.TransactionStatus
)) {
39 Request
->Token
->TransactionStatus
= Request
->Packet
.TransactionStatus
;
42 RemoveEntryList (&Request
->Link
);
45 gBS
->SignalEvent (Request
->Token
->Event
);
52 Send command SET_RELATIVE_ADDRESS to the device to set the device address.
54 @param[in] Device A pointer to the SD_DEVICE instance.
55 @param[out] Rca The relative device address to assign.
57 @retval EFI_SUCCESS The request is executed successfully.
58 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
59 @retval Others The request could not be executed successfully.
69 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
70 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
71 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
72 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
74 PassThru
= Device
->Private
->PassThru
;
76 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
77 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
78 ZeroMem (&Packet
, sizeof (Packet
));
79 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
80 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
81 Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
83 SdMmcCmdBlk
.CommandIndex
= SD_SET_RELATIVE_ADDR
;
84 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeBcr
;
85 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR6
;
87 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &Packet
, NULL
);
88 if (!EFI_ERROR (Status
)) {
89 DEBUG ((DEBUG_INFO
, "Set RCA succeeds with Resp0 = 0x%x\n", SdMmcStatusBlk
.Resp0
));
90 *Rca
= (UINT16
)(SdMmcStatusBlk
.Resp0
>> 16);
97 Send command SELECT to the device to select/deselect the device.
99 @param[in] Device A pointer to the SD_DEVICE instance.
100 @param[in] Rca The relative device address to use.
102 @retval EFI_SUCCESS The request is executed successfully.
103 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
104 @retval Others The request could not be executed successfully.
109 IN SD_DEVICE
*Device
,
114 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
115 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
116 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
117 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
119 PassThru
= Device
->Private
->PassThru
;
121 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
122 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
123 ZeroMem (&Packet
, sizeof (Packet
));
124 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
125 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
126 Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
128 SdMmcCmdBlk
.CommandIndex
= SD_SELECT_DESELECT_CARD
;
129 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
131 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1b
;
133 SdMmcCmdBlk
.CommandArgument
= (UINT32
)Rca
<< 16;
135 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &Packet
, NULL
);
141 Send command SEND_STATUS to the device to get device status.
143 @param[in] Device A pointer to the SD_DEVICE instance.
144 @param[in] Rca The relative device address to use.
145 @param[out] DevStatus The buffer to store the device status.
147 @retval EFI_SUCCESS The request is executed successfully.
148 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
149 @retval Others The request could not be executed successfully.
154 IN SD_DEVICE
*Device
,
156 OUT UINT32
*DevStatus
160 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
161 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
162 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
163 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
165 PassThru
= Device
->Private
->PassThru
;
167 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
168 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
169 ZeroMem (&Packet
, sizeof (Packet
));
170 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
171 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
172 Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
174 SdMmcCmdBlk
.CommandIndex
= SD_SEND_STATUS
;
175 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
176 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
177 SdMmcCmdBlk
.CommandArgument
= (UINT32
)Rca
<< 16;
179 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &Packet
, NULL
);
180 if (!EFI_ERROR (Status
)) {
181 CopyMem (DevStatus
, &SdMmcStatusBlk
.Resp0
, sizeof (UINT32
));
187 Send command SEND_CSD to the device to get the CSD register data.
189 @param[in] Device A pointer to the SD_DEVICE instance.
190 @param[in] Rca The relative device address to use.
191 @param[out] Csd The buffer to store the SD_CSD register data.
193 @retval EFI_SUCCESS The request is executed successfully.
194 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
195 @retval Others The request could not be executed successfully.
200 IN SD_DEVICE
*Device
,
206 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
207 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
208 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
209 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
211 PassThru
= Device
->Private
->PassThru
;
213 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
214 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
215 ZeroMem (&Packet
, sizeof (Packet
));
216 ZeroMem (Csd
, sizeof (SD_CSD
));
218 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
219 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
220 Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
222 SdMmcCmdBlk
.CommandIndex
= SD_SEND_CSD
;
223 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
224 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR2
;
225 SdMmcCmdBlk
.CommandArgument
= (UINT32
)Rca
<< 16;
227 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &Packet
, NULL
);
229 if (!EFI_ERROR (Status
)) {
231 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
233 CopyMem (((UINT8
*)Csd
) + 1, &SdMmcStatusBlk
.Resp0
, sizeof (SD_CSD
) - 1);
240 Send command SEND_CID to the device to get the CID register data.
242 @param[in] Device A pointer to the SD_DEVICE instance.
243 @param[in] Rca The relative device address to use.
244 @param[out] Cid The buffer to store the SD_CID register data.
246 @retval EFI_SUCCESS The request is executed successfully.
247 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
248 @retval Others The request could not be executed successfully.
253 IN SD_DEVICE
*Device
,
259 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
260 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
261 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
262 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
264 PassThru
= Device
->Private
->PassThru
;
266 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
267 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
268 ZeroMem (&Packet
, sizeof (Packet
));
269 ZeroMem (Cid
, sizeof (SD_CID
));
271 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
272 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
273 Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
275 SdMmcCmdBlk
.CommandIndex
= SD_SEND_CID
;
276 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
277 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR2
;
278 SdMmcCmdBlk
.CommandArgument
= (UINT32
)Rca
<< 16;
280 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &Packet
, NULL
);
282 if (!EFI_ERROR (Status
)) {
284 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
286 CopyMem (((UINT8
*)Cid
) + 1, &SdMmcStatusBlk
.Resp0
, sizeof (SD_CID
) - 1);
293 Read/write single block through sync or async I/O request.
295 @param[in] Device A pointer to the SD_DEVICE instance.
296 @param[in] Lba The starting logical block address to be read/written.
297 The caller is responsible for reading/writing to only
298 legitimate locations.
299 @param[in] Buffer A pointer to the destination/source buffer for the data.
300 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
301 @param[in] IsRead Indicates it is a read or write operation.
302 @param[in] Token A pointer to the token associated with the transaction.
303 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
304 This parameter is only meaningful in async I/O request.
306 @retval EFI_SUCCESS The request is executed successfully.
307 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
308 @retval Others The request could not be executed successfully.
313 IN SD_DEVICE
*Device
,
318 IN EFI_BLOCK_IO2_TOKEN
*Token
,
323 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
324 SD_REQUEST
*RwSingleBlkReq
;
327 RwSingleBlkReq
= NULL
;
328 PassThru
= Device
->Private
->PassThru
;
330 RwSingleBlkReq
= AllocateZeroPool (sizeof (SD_REQUEST
));
331 if (RwSingleBlkReq
== NULL
) {
332 Status
= EFI_OUT_OF_RESOURCES
;
336 RwSingleBlkReq
->Signature
= SD_REQUEST_SIGNATURE
;
337 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
338 InsertTailList (&Device
->Queue
, &RwSingleBlkReq
->Link
);
339 gBS
->RestoreTPL (OldTpl
);
340 RwSingleBlkReq
->Packet
.SdMmcCmdBlk
= &RwSingleBlkReq
->SdMmcCmdBlk
;
341 RwSingleBlkReq
->Packet
.SdMmcStatusBlk
= &RwSingleBlkReq
->SdMmcStatusBlk
;
343 // Calculate timeout value through the below formula.
344 // Timeout = (transfer size) / (2MB/s).
345 // Taking 2MB/s as divisor as it's the lowest transfer speed
347 // Refer to SD Physical Layer Simplified spec section 3.4 for details.
349 RwSingleBlkReq
->Packet
.Timeout
= (BufferSize
/ (2 * 1024 * 1024) + 1) * 1000 * 1000;
352 RwSingleBlkReq
->Packet
.InDataBuffer
= Buffer
;
353 RwSingleBlkReq
->Packet
.InTransferLength
= (UINT32
)BufferSize
;
355 RwSingleBlkReq
->SdMmcCmdBlk
.CommandIndex
= SD_READ_SINGLE_BLOCK
;
356 RwSingleBlkReq
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAdtc
;
357 RwSingleBlkReq
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
359 RwSingleBlkReq
->Packet
.OutDataBuffer
= Buffer
;
360 RwSingleBlkReq
->Packet
.OutTransferLength
= (UINT32
)BufferSize
;
362 RwSingleBlkReq
->SdMmcCmdBlk
.CommandIndex
= SD_WRITE_SINGLE_BLOCK
;
363 RwSingleBlkReq
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAdtc
;
364 RwSingleBlkReq
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
367 if (Device
->SectorAddressing
) {
368 RwSingleBlkReq
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)Lba
;
370 RwSingleBlkReq
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)MultU64x32 (Lba
, Device
->BlockMedia
.BlockSize
);
373 RwSingleBlkReq
->IsEnd
= IsEnd
;
374 RwSingleBlkReq
->Token
= Token
;
376 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
377 Status
= gBS
->CreateEvent (
382 &RwSingleBlkReq
->Event
384 if (EFI_ERROR (Status
)) {
388 RwSingleBlkReq
->Event
= NULL
;
391 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &RwSingleBlkReq
->Packet
, RwSingleBlkReq
->Event
);
394 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
396 // For asynchronous operation, only free request and event in error case.
397 // The request and event will be freed in asynchronous callback for success case.
399 if (EFI_ERROR (Status
) && (RwSingleBlkReq
!= NULL
)) {
400 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
401 RemoveEntryList (&RwSingleBlkReq
->Link
);
402 gBS
->RestoreTPL (OldTpl
);
403 if (RwSingleBlkReq
->Event
!= NULL
) {
404 gBS
->CloseEvent (RwSingleBlkReq
->Event
);
406 FreePool (RwSingleBlkReq
);
410 // For synchronous operation, free request whatever the execution result is.
412 if (RwSingleBlkReq
!= NULL
) {
413 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
414 RemoveEntryList (&RwSingleBlkReq
->Link
);
415 gBS
->RestoreTPL (OldTpl
);
416 FreePool (RwSingleBlkReq
);
424 Read/write multiple blocks through sync or async I/O request.
426 @param[in] Device A pointer to the SD_DEVICE instance.
427 @param[in] Lba The starting logical block address to be read/written.
428 The caller is responsible for reading/writing to only
429 legitimate locations.
430 @param[in] Buffer A pointer to the destination/source buffer for the data.
431 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
432 @param[in] IsRead Indicates it is a read or write operation.
433 @param[in] Token A pointer to the token associated with the transaction.
434 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
435 This parameter is only meaningful in async I/O request.
437 @retval EFI_SUCCESS The request is executed successfully.
438 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
439 @retval Others The request could not be executed successfully.
444 IN SD_DEVICE
*Device
,
449 IN EFI_BLOCK_IO2_TOKEN
*Token
,
454 SD_REQUEST
*RwMultiBlkReq
;
455 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
458 RwMultiBlkReq
= NULL
;
460 PassThru
= Device
->Private
->PassThru
;
462 RwMultiBlkReq
= AllocateZeroPool (sizeof (SD_REQUEST
));
463 if (RwMultiBlkReq
== NULL
) {
464 Status
= EFI_OUT_OF_RESOURCES
;
468 RwMultiBlkReq
->Signature
= SD_REQUEST_SIGNATURE
;
469 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
470 InsertTailList (&Device
->Queue
, &RwMultiBlkReq
->Link
);
471 gBS
->RestoreTPL (OldTpl
);
472 RwMultiBlkReq
->Packet
.SdMmcCmdBlk
= &RwMultiBlkReq
->SdMmcCmdBlk
;
473 RwMultiBlkReq
->Packet
.SdMmcStatusBlk
= &RwMultiBlkReq
->SdMmcStatusBlk
;
475 // Calculate timeout value through the below formula.
476 // Timeout = (transfer size) / (2MB/s).
477 // Taking 2MB/s as divisor as it's the lowest transfer speed
479 // Refer to SD Physical Layer Simplified spec section 3.4 for details.
481 RwMultiBlkReq
->Packet
.Timeout
= (BufferSize
/ (2 * 1024 * 1024) + 1) * 1000 * 1000;
484 RwMultiBlkReq
->Packet
.InDataBuffer
= Buffer
;
485 RwMultiBlkReq
->Packet
.InTransferLength
= (UINT32
)BufferSize
;
487 RwMultiBlkReq
->SdMmcCmdBlk
.CommandIndex
= SD_READ_MULTIPLE_BLOCK
;
488 RwMultiBlkReq
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAdtc
;
489 RwMultiBlkReq
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
491 RwMultiBlkReq
->Packet
.OutDataBuffer
= Buffer
;
492 RwMultiBlkReq
->Packet
.OutTransferLength
= (UINT32
)BufferSize
;
494 RwMultiBlkReq
->SdMmcCmdBlk
.CommandIndex
= SD_WRITE_MULTIPLE_BLOCK
;
495 RwMultiBlkReq
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAdtc
;
496 RwMultiBlkReq
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
499 if (Device
->SectorAddressing
) {
500 RwMultiBlkReq
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)Lba
;
502 RwMultiBlkReq
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)MultU64x32 (Lba
, Device
->BlockMedia
.BlockSize
);
505 RwMultiBlkReq
->IsEnd
= IsEnd
;
506 RwMultiBlkReq
->Token
= Token
;
508 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
509 Status
= gBS
->CreateEvent (
514 &RwMultiBlkReq
->Event
516 if (EFI_ERROR (Status
)) {
520 RwMultiBlkReq
->Event
= NULL
;
523 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &RwMultiBlkReq
->Packet
, RwMultiBlkReq
->Event
);
526 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
528 // For asynchronous operation, only free request and event in error case.
529 // The request and event will be freed in asynchronous callback for success case.
531 if (EFI_ERROR (Status
) && (RwMultiBlkReq
!= NULL
)) {
532 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
533 RemoveEntryList (&RwMultiBlkReq
->Link
);
534 gBS
->RestoreTPL (OldTpl
);
535 if (RwMultiBlkReq
->Event
!= NULL
) {
536 gBS
->CloseEvent (RwMultiBlkReq
->Event
);
538 FreePool (RwMultiBlkReq
);
542 // For synchronous operation, free request whatever the execution result is.
544 if (RwMultiBlkReq
!= NULL
) {
545 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
546 RemoveEntryList (&RwMultiBlkReq
->Link
);
547 gBS
->RestoreTPL (OldTpl
);
548 FreePool (RwMultiBlkReq
);
556 This function transfers data from/to the sd memory card device.
558 @param[in] Device A pointer to the SD_DEVICE instance.
559 @param[in] MediaId The media ID that the read/write request is for.
560 @param[in] Lba The starting logical block address to be read/written.
561 The caller is responsible for reading/writing to only
562 legitimate locations.
563 @param[in, out] Buffer A pointer to the destination/source buffer for the data.
564 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
565 @param[in] IsRead Indicates it is a read or write operation.
566 @param[in, out] Token A pointer to the token associated with the transaction.
568 @retval EFI_SUCCESS The data was read/written correctly to the device.
569 @retval EFI_WRITE_PROTECTED The device can not be read/written to.
570 @retval EFI_DEVICE_ERROR The device reported an error while performing the read/write.
571 @retval EFI_NO_MEDIA There is no media in the device.
572 @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.
573 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
574 @retval EFI_INVALID_PARAMETER The read/write request contains LBAs that are not valid,
575 or the buffer is not on proper alignment.
580 IN SD_DEVICE
*Device
,
586 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
590 EFI_BLOCK_IO_MEDIA
*Media
;
598 Status
= EFI_SUCCESS
;
599 Media
= &Device
->BlockMedia
;
602 if (MediaId
!= Media
->MediaId
) {
603 return EFI_MEDIA_CHANGED
;
606 if (!IsRead
&& Media
->ReadOnly
) {
607 return EFI_WRITE_PROTECTED
;
613 if (Buffer
== NULL
) {
614 return EFI_INVALID_PARAMETER
;
617 if (BufferSize
== 0) {
618 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
619 Token
->TransactionStatus
= EFI_SUCCESS
;
620 gBS
->SignalEvent (Token
->Event
);
625 BlockSize
= Media
->BlockSize
;
626 if ((BufferSize
% BlockSize
) != 0) {
627 return EFI_BAD_BUFFER_SIZE
;
630 BlockNum
= BufferSize
/ BlockSize
;
631 if ((Lba
+ BlockNum
- 1) > Media
->LastBlock
) {
632 return EFI_INVALID_PARAMETER
;
635 IoAlign
= Media
->IoAlign
;
636 if (IoAlign
> 0 && (((UINTN
) Buffer
& (IoAlign
- 1)) != 0)) {
637 return EFI_INVALID_PARAMETER
;
640 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
641 Token
->TransactionStatus
= EFI_SUCCESS
;
645 // Start to execute data transfer. The max block number in single cmd is 65535 blocks.
647 Remaining
= BlockNum
;
650 while (Remaining
> 0) {
651 if (Remaining
<= MaxBlock
) {
652 BlockNum
= Remaining
;
658 BufferSize
= BlockNum
* BlockSize
;
660 Status
= SdRwSingleBlock (Device
, Lba
, Buffer
, BufferSize
, IsRead
, Token
, LastRw
);
662 Status
= SdRwMultiBlocks (Device
, Lba
, Buffer
, BufferSize
, IsRead
, Token
, LastRw
);
664 if (EFI_ERROR (Status
)) {
667 DEBUG ((DEBUG_BLKIO
, "Sd%a(): Lba 0x%x BlkNo 0x%x Event %p with %r\n",
668 IsRead
? "Read" : "Write", Lba
, BlockNum
,
669 (Token
!= NULL
) ? Token
->Event
: NULL
, Status
));
671 Buffer
= (UINT8
*)Buffer
+ BufferSize
;
672 Remaining
-= BlockNum
;
679 Reset the Block Device.
681 @param This Indicates a pointer to the calling context.
682 @param ExtendedVerification Driver may perform diagnostics on reset.
684 @retval EFI_SUCCESS The device was reset.
685 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
692 IN EFI_BLOCK_IO_PROTOCOL
*This
,
693 IN BOOLEAN ExtendedVerification
698 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
700 Device
= SD_DEVICE_DATA_FROM_BLKIO (This
);
702 PassThru
= Device
->Private
->PassThru
;
703 Status
= PassThru
->ResetDevice (PassThru
, Device
->Slot
);
704 if (EFI_ERROR (Status
)) {
705 Status
= EFI_DEVICE_ERROR
;
712 Read BufferSize bytes from Lba into Buffer.
714 @param This Indicates a pointer to the calling context.
715 @param MediaId Id of the media, changes every time the media is replaced.
716 @param Lba The starting Logical Block Address to read from
717 @param BufferSize Size of Buffer, must be a multiple of device block size.
718 @param Buffer A pointer to the destination buffer for the data. The caller is
719 responsible for either having implicit or explicit ownership of the buffer.
721 @retval EFI_SUCCESS The data was read correctly from the device.
722 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
723 @retval EFI_NO_MEDIA There is no media in the device.
724 @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.
725 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
726 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
727 or the buffer is not on proper alignment.
733 IN EFI_BLOCK_IO_PROTOCOL
*This
,
743 Device
= SD_DEVICE_DATA_FROM_BLKIO (This
);
745 Status
= SdReadWrite (Device
, MediaId
, Lba
, Buffer
, BufferSize
, TRUE
, NULL
);
750 Write BufferSize bytes from Lba into Buffer.
752 @param This Indicates a pointer to the calling context.
753 @param MediaId The media ID that the write request is for.
754 @param Lba The starting logical block address to be written. The caller is
755 responsible for writing to only legitimate locations.
756 @param BufferSize Size of Buffer, must be a multiple of device block size.
757 @param Buffer A pointer to the source buffer for the data.
759 @retval EFI_SUCCESS The data was written correctly to the device.
760 @retval EFI_WRITE_PROTECTED The device can not be written to.
761 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
762 @retval EFI_NO_MEDIA There is no media in the device.
763 @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.
764 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
765 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
766 or the buffer is not on proper alignment.
772 IN EFI_BLOCK_IO_PROTOCOL
*This
,
782 Device
= SD_DEVICE_DATA_FROM_BLKIO (This
);
784 Status
= SdReadWrite (Device
, MediaId
, Lba
, Buffer
, BufferSize
, FALSE
, NULL
);
789 Flush the Block Device.
791 @param This Indicates a pointer to the calling context.
793 @retval EFI_SUCCESS All outstanding data was written to the device
794 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data
795 @retval EFI_NO_MEDIA There is no media in the device.
801 IN EFI_BLOCK_IO_PROTOCOL
*This
811 Reset the Block Device.
813 @param[in] This Indicates a pointer to the calling context.
814 @param[in] ExtendedVerification Driver may perform diagnostics on reset.
816 @retval EFI_SUCCESS The device was reset.
817 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
824 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
825 IN BOOLEAN ExtendedVerification
830 LIST_ENTRY
*NextLink
;
834 Device
= SD_DEVICE_DATA_FROM_BLKIO2 (This
);
836 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
837 for (Link
= GetFirstNode (&Device
->Queue
);
838 !IsNull (&Device
->Queue
, Link
);
840 NextLink
= GetNextNode (&Device
->Queue
, Link
);
841 RemoveEntryList (Link
);
843 Request
= SD_REQUEST_FROM_LINK (Link
);
845 gBS
->CloseEvent (Request
->Event
);
846 Request
->Token
->TransactionStatus
= EFI_ABORTED
;
848 if (Request
->IsEnd
) {
849 gBS
->SignalEvent (Request
->Token
->Event
);
854 gBS
->RestoreTPL (OldTpl
);
860 Read BufferSize bytes from Lba into Buffer.
862 @param[in] This Indicates a pointer to the calling context.
863 @param[in] MediaId Id of the media, changes every time the media is replaced.
864 @param[in] Lba The starting Logical Block Address to read from.
865 @param[in, out] Token A pointer to the token associated with the transaction.
866 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
867 @param[out] Buffer A pointer to the destination buffer for the data. The caller is
868 responsible for either having implicit or explicit ownership of the buffer.
870 @retval EFI_SUCCESS The read request was queued if Event is not NULL.
871 The data was read correctly from the device if
873 @retval EFI_DEVICE_ERROR The device reported an error while performing
875 @retval EFI_NO_MEDIA There is no media in the device.
876 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
877 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the
878 intrinsic block size of the device.
879 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
880 or the buffer is not on proper alignment.
881 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
888 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
891 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
899 Device
= SD_DEVICE_DATA_FROM_BLKIO2 (This
);
901 Status
= SdReadWrite (Device
, MediaId
, Lba
, Buffer
, BufferSize
, TRUE
, Token
);
906 Write BufferSize bytes from Lba into Buffer.
908 @param[in] This Indicates a pointer to the calling context.
909 @param[in] MediaId The media ID that the write request is for.
910 @param[in] Lba The starting logical block address to be written. The
911 caller is responsible for writing to only legitimate
913 @param[in, out] Token A pointer to the token associated with the transaction.
914 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
915 @param[in] Buffer A pointer to the source buffer for the data.
917 @retval EFI_SUCCESS The data was written correctly to the device.
918 @retval EFI_WRITE_PROTECTED The device can not be written to.
919 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
920 @retval EFI_NO_MEDIA There is no media in the device.
921 @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.
922 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
923 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
924 or the buffer is not on proper alignment.
930 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
933 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
941 Device
= SD_DEVICE_DATA_FROM_BLKIO2 (This
);
943 Status
= SdReadWrite (Device
, MediaId
, Lba
, Buffer
, BufferSize
, FALSE
, Token
);
948 Flush the Block Device.
950 @param[in] This Indicates a pointer to the calling context.
951 @param[in, out] Token A pointer to the token associated with the transaction.
953 @retval EFI_SUCCESS All outstanding data was written to the device
954 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data
955 @retval EFI_NO_MEDIA There is no media in the device.
961 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
962 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
966 // Signal event and return directly.
968 if (Token
!= NULL
&& Token
->Event
!= NULL
) {
969 Token
->TransactionStatus
= EFI_SUCCESS
;
970 gBS
->SignalEvent (Token
->Event
);
977 Set the erase start address through sync or async I/O request.
979 @param[in] Device A pointer to the SD_DEVICE instance.
980 @param[in] StartLba The starting logical block address to be erased.
981 @param[in] Token A pointer to the token associated with the transaction.
982 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
983 This parameter is only meaningful in async I/O request.
985 @retval EFI_SUCCESS The request is executed successfully.
986 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
987 @retval Others The request could not be executed successfully.
992 IN SD_DEVICE
*Device
,
994 IN EFI_BLOCK_IO2_TOKEN
*Token
,
999 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
1000 SD_REQUEST
*EraseBlockStart
;
1003 EraseBlockStart
= NULL
;
1004 PassThru
= Device
->Private
->PassThru
;
1006 EraseBlockStart
= AllocateZeroPool (sizeof (SD_REQUEST
));
1007 if (EraseBlockStart
== NULL
) {
1008 Status
= EFI_OUT_OF_RESOURCES
;
1012 EraseBlockStart
->Signature
= SD_REQUEST_SIGNATURE
;
1013 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1014 InsertTailList (&Device
->Queue
, &EraseBlockStart
->Link
);
1015 gBS
->RestoreTPL (OldTpl
);
1016 EraseBlockStart
->Packet
.SdMmcCmdBlk
= &EraseBlockStart
->SdMmcCmdBlk
;
1017 EraseBlockStart
->Packet
.SdMmcStatusBlk
= &EraseBlockStart
->SdMmcStatusBlk
;
1018 EraseBlockStart
->Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
1020 EraseBlockStart
->SdMmcCmdBlk
.CommandIndex
= SD_ERASE_WR_BLK_START
;
1021 EraseBlockStart
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
1022 EraseBlockStart
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
1024 if (Device
->SectorAddressing
) {
1025 EraseBlockStart
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)StartLba
;
1027 EraseBlockStart
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)MultU64x32 (StartLba
, Device
->BlockMedia
.BlockSize
);
1030 EraseBlockStart
->IsEnd
= IsEnd
;
1031 EraseBlockStart
->Token
= Token
;
1033 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1034 Status
= gBS
->CreateEvent (
1039 &EraseBlockStart
->Event
1041 if (EFI_ERROR (Status
)) {
1045 EraseBlockStart
->Event
= NULL
;
1048 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &EraseBlockStart
->Packet
, EraseBlockStart
->Event
);
1051 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1053 // For asynchronous operation, only free request and event in error case.
1054 // The request and event will be freed in asynchronous callback for success case.
1056 if (EFI_ERROR (Status
) && (EraseBlockStart
!= NULL
)) {
1057 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1058 RemoveEntryList (&EraseBlockStart
->Link
);
1059 gBS
->RestoreTPL (OldTpl
);
1060 if (EraseBlockStart
->Event
!= NULL
) {
1061 gBS
->CloseEvent (EraseBlockStart
->Event
);
1063 FreePool (EraseBlockStart
);
1067 // For synchronous operation, free request whatever the execution result is.
1069 if (EraseBlockStart
!= NULL
) {
1070 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1071 RemoveEntryList (&EraseBlockStart
->Link
);
1072 gBS
->RestoreTPL (OldTpl
);
1073 FreePool (EraseBlockStart
);
1081 Set the erase end address through sync or async I/O request.
1083 @param[in] Device A pointer to the SD_DEVICE instance.
1084 @param[in] EndLba The ending logical block address to be erased.
1085 @param[in] Token A pointer to the token associated with the transaction.
1086 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
1087 This parameter is only meaningful in async I/O request.
1089 @retval EFI_SUCCESS The request is executed successfully.
1090 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
1091 @retval Others The request could not be executed successfully.
1096 IN SD_DEVICE
*Device
,
1098 IN EFI_BLOCK_IO2_TOKEN
*Token
,
1103 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
1104 SD_REQUEST
*EraseBlockEnd
;
1107 EraseBlockEnd
= NULL
;
1108 PassThru
= Device
->Private
->PassThru
;
1110 EraseBlockEnd
= AllocateZeroPool (sizeof (SD_REQUEST
));
1111 if (EraseBlockEnd
== NULL
) {
1112 Status
= EFI_OUT_OF_RESOURCES
;
1116 EraseBlockEnd
->Signature
= SD_REQUEST_SIGNATURE
;
1117 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1118 InsertTailList (&Device
->Queue
, &EraseBlockEnd
->Link
);
1119 gBS
->RestoreTPL (OldTpl
);
1120 EraseBlockEnd
->Packet
.SdMmcCmdBlk
= &EraseBlockEnd
->SdMmcCmdBlk
;
1121 EraseBlockEnd
->Packet
.SdMmcStatusBlk
= &EraseBlockEnd
->SdMmcStatusBlk
;
1122 EraseBlockEnd
->Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
1124 EraseBlockEnd
->SdMmcCmdBlk
.CommandIndex
= SD_ERASE_WR_BLK_END
;
1125 EraseBlockEnd
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
1126 EraseBlockEnd
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
1128 if (Device
->SectorAddressing
) {
1129 EraseBlockEnd
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)EndLba
;
1131 EraseBlockEnd
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)MultU64x32 (EndLba
, Device
->BlockMedia
.BlockSize
);
1134 EraseBlockEnd
->IsEnd
= IsEnd
;
1135 EraseBlockEnd
->Token
= Token
;
1137 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1138 Status
= gBS
->CreateEvent (
1143 &EraseBlockEnd
->Event
1145 if (EFI_ERROR (Status
)) {
1149 EraseBlockEnd
->Event
= NULL
;
1152 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &EraseBlockEnd
->Packet
, EraseBlockEnd
->Event
);
1155 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1157 // For asynchronous operation, only free request and event in error case.
1158 // The request and event will be freed in asynchronous callback for success case.
1160 if (EFI_ERROR (Status
) && (EraseBlockEnd
!= NULL
)) {
1161 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1162 RemoveEntryList (&EraseBlockEnd
->Link
);
1163 gBS
->RestoreTPL (OldTpl
);
1164 if (EraseBlockEnd
->Event
!= NULL
) {
1165 gBS
->CloseEvent (EraseBlockEnd
->Event
);
1167 FreePool (EraseBlockEnd
);
1171 // For synchronous operation, free request whatever the execution result is.
1173 if (EraseBlockEnd
!= NULL
) {
1174 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1175 RemoveEntryList (&EraseBlockEnd
->Link
);
1176 gBS
->RestoreTPL (OldTpl
);
1177 FreePool (EraseBlockEnd
);
1185 Erase specified blocks through sync or async I/O request.
1187 @param[in] Device A pointer to the SD_DEVICE instance.
1188 @param[in] Token A pointer to the token associated with the transaction.
1189 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
1190 This parameter is only meaningful in async I/O request.
1192 @retval EFI_SUCCESS The request is executed successfully.
1193 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
1194 @retval Others The request could not be executed successfully.
1199 IN SD_DEVICE
*Device
,
1200 IN EFI_BLOCK_IO2_TOKEN
*Token
,
1205 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
1206 SD_REQUEST
*EraseBlock
;
1210 PassThru
= Device
->Private
->PassThru
;
1212 EraseBlock
= AllocateZeroPool (sizeof (SD_REQUEST
));
1213 if (EraseBlock
== NULL
) {
1214 Status
= EFI_OUT_OF_RESOURCES
;
1218 EraseBlock
->Signature
= SD_REQUEST_SIGNATURE
;
1219 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1220 InsertTailList (&Device
->Queue
, &EraseBlock
->Link
);
1221 gBS
->RestoreTPL (OldTpl
);
1222 EraseBlock
->Packet
.SdMmcCmdBlk
= &EraseBlock
->SdMmcCmdBlk
;
1223 EraseBlock
->Packet
.SdMmcStatusBlk
= &EraseBlock
->SdMmcStatusBlk
;
1224 EraseBlock
->Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
1226 EraseBlock
->SdMmcCmdBlk
.CommandIndex
= SD_ERASE
;
1227 EraseBlock
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
1228 EraseBlock
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1b
;
1230 EraseBlock
->IsEnd
= IsEnd
;
1231 EraseBlock
->Token
= Token
;
1233 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1234 Status
= gBS
->CreateEvent (
1241 if (EFI_ERROR (Status
)) {
1245 EraseBlock
->Event
= NULL
;
1248 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &EraseBlock
->Packet
, EraseBlock
->Event
);
1251 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1253 // For asynchronous operation, only free request and event in error case.
1254 // The request and event will be freed in asynchronous callback for success case.
1256 if (EFI_ERROR (Status
) && (EraseBlock
!= NULL
)) {
1257 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1258 RemoveEntryList (&EraseBlock
->Link
);
1259 gBS
->RestoreTPL (OldTpl
);
1260 if (EraseBlock
->Event
!= NULL
) {
1261 gBS
->CloseEvent (EraseBlock
->Event
);
1263 FreePool (EraseBlock
);
1267 // For synchronous operation, free request whatever the execution result is.
1269 if (EraseBlock
!= NULL
) {
1270 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1271 RemoveEntryList (&EraseBlock
->Link
);
1272 gBS
->RestoreTPL (OldTpl
);
1273 FreePool (EraseBlock
);
1281 Erase a specified number of device blocks.
1283 @param[in] This Indicates a pointer to the calling context.
1284 @param[in] MediaId The media ID that the erase request is for.
1285 @param[in] Lba The starting logical block address to be
1286 erased. The caller is responsible for erasing
1287 only legitimate locations.
1288 @param[in, out] Token A pointer to the token associated with the
1290 @param[in] Size The size in bytes to be erased. This must be
1291 a multiple of the physical block size of the
1294 @retval EFI_SUCCESS The erase request was queued if Event is not
1295 NULL. The data was erased correctly to the
1296 device if the Event is NULL.to the device.
1297 @retval EFI_WRITE_PROTECTED The device cannot be erased due to write
1299 @retval EFI_DEVICE_ERROR The device reported an error while attempting
1300 to perform the erase operation.
1301 @retval EFI_INVALID_PARAMETER The erase request contains LBAs that are not
1303 @retval EFI_NO_MEDIA There is no media in the device.
1304 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1310 IN EFI_ERASE_BLOCK_PROTOCOL
*This
,
1313 IN OUT EFI_ERASE_BLOCK_TOKEN
*Token
,
1318 EFI_BLOCK_IO_MEDIA
*Media
;
1324 Status
= EFI_SUCCESS
;
1325 Device
= SD_DEVICE_DATA_FROM_ERASEBLK (This
);
1326 Media
= &Device
->BlockMedia
;
1328 if (MediaId
!= Media
->MediaId
) {
1329 return EFI_MEDIA_CHANGED
;
1332 if (Media
->ReadOnly
) {
1333 return EFI_WRITE_PROTECTED
;
1337 // Check parameters.
1339 BlockSize
= Media
->BlockSize
;
1340 if ((Size
% BlockSize
) != 0) {
1341 return EFI_INVALID_PARAMETER
;
1344 BlockNum
= Size
/ BlockSize
;
1345 if ((Lba
+ BlockNum
- 1) > Media
->LastBlock
) {
1346 return EFI_INVALID_PARAMETER
;
1349 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1350 Token
->TransactionStatus
= EFI_SUCCESS
;
1353 LastLba
= Lba
+ BlockNum
- 1;
1355 Status
= SdEraseBlockStart (Device
, Lba
, (EFI_BLOCK_IO2_TOKEN
*)Token
, FALSE
);
1356 if (EFI_ERROR (Status
)) {
1360 Status
= SdEraseBlockEnd (Device
, LastLba
, (EFI_BLOCK_IO2_TOKEN
*)Token
, FALSE
);
1361 if (EFI_ERROR (Status
)) {
1365 Status
= SdEraseBlock (Device
, (EFI_BLOCK_IO2_TOKEN
*)Token
, TRUE
);
1366 if (EFI_ERROR (Status
)) {
1372 "SdEraseBlocks(): Lba 0x%x BlkNo 0x%x Event %p with %r\n",
1375 (Token
!= NULL
) ? Token
->Event
: NULL
,