2 The helper functions for BlockIo and BlockIo2 protocol.
4 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Nonblocking I/O callback funtion when the event is signaled.
20 @param[in] Event The Event this notify function registered to.
21 @param[in] Context Pointer to the context data registered to the
34 gBS
->CloseEvent (Event
);
36 Request
= (SD_REQUEST
*) Context
;
39 DEBUG ((EFI_D_INFO
, "Sd Async Request: CmdIndex[%d] Arg[%08x] %r\n",
40 Request
->SdMmcCmdBlk
.CommandIndex
, Request
->SdMmcCmdBlk
.CommandArgument
,
41 Request
->Packet
.TransactionStatus
));
44 if (EFI_ERROR (Request
->Packet
.TransactionStatus
)) {
45 Request
->Token
->TransactionStatus
= Request
->Packet
.TransactionStatus
;
48 RemoveEntryList (&Request
->Link
);
51 gBS
->SignalEvent (Request
->Token
->Event
);
58 Send command SET_RELATIVE_ADDRESS to the device to set the device address.
60 @param[in] Device A pointer to the SD_DEVICE instance.
61 @param[out] Rca The relative device address to assign.
63 @retval EFI_SUCCESS The request is executed successfully.
64 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
65 @retval Others The request could not be executed successfully.
75 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
76 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
77 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
78 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
80 PassThru
= Device
->Private
->PassThru
;
82 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
83 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
84 ZeroMem (&Packet
, sizeof (Packet
));
85 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
86 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
87 Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
89 SdMmcCmdBlk
.CommandIndex
= SD_SET_RELATIVE_ADDR
;
90 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeBcr
;
91 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR6
;
93 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &Packet
, NULL
);
94 if (!EFI_ERROR (Status
)) {
95 DEBUG ((EFI_D_INFO
, "Set RCA succeeds with Resp0 = 0x%x\n", SdMmcStatusBlk
.Resp0
));
96 *Rca
= (UINT16
)(SdMmcStatusBlk
.Resp0
>> 16);
103 Send command SELECT to the device to select/deselect the device.
105 @param[in] Device A pointer to the SD_DEVICE instance.
106 @param[in] Rca The relative device address to use.
108 @retval EFI_SUCCESS The request is executed successfully.
109 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
110 @retval Others The request could not be executed successfully.
115 IN SD_DEVICE
*Device
,
120 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
121 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
122 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
123 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
125 PassThru
= Device
->Private
->PassThru
;
127 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
128 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
129 ZeroMem (&Packet
, sizeof (Packet
));
130 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
131 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
132 Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
134 SdMmcCmdBlk
.CommandIndex
= SD_SELECT_DESELECT_CARD
;
135 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
137 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1b
;
139 SdMmcCmdBlk
.CommandArgument
= (UINT32
)Rca
<< 16;
141 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &Packet
, NULL
);
147 Send command SEND_STATUS to the device to get device status.
149 @param[in] Device A pointer to the SD_DEVICE instance.
150 @param[in] Rca The relative device address to use.
151 @param[out] DevStatus The buffer to store the device status.
153 @retval EFI_SUCCESS The request is executed successfully.
154 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
155 @retval Others The request could not be executed successfully.
160 IN SD_DEVICE
*Device
,
162 OUT UINT32
*DevStatus
166 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
167 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
168 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
169 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
171 PassThru
= Device
->Private
->PassThru
;
173 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
174 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
175 ZeroMem (&Packet
, sizeof (Packet
));
176 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
177 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
178 Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
180 SdMmcCmdBlk
.CommandIndex
= SD_SEND_STATUS
;
181 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
182 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
183 SdMmcCmdBlk
.CommandArgument
= (UINT32
)Rca
<< 16;
185 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &Packet
, NULL
);
186 if (!EFI_ERROR (Status
)) {
187 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
);
412 FreePool (RwSingleBlkReq
);
416 // For synchronous operation, free request whatever the execution result is.
418 if (RwSingleBlkReq
!= NULL
) {
419 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
420 RemoveEntryList (&RwSingleBlkReq
->Link
);
421 gBS
->RestoreTPL (OldTpl
);
422 FreePool (RwSingleBlkReq
);
430 Read/write multiple blocks through sync or async I/O request.
432 @param[in] Device A pointer to the SD_DEVICE instance.
433 @param[in] Lba The starting logical block address to be read/written.
434 The caller is responsible for reading/writing to only
435 legitimate locations.
436 @param[in] Buffer A pointer to the destination/source buffer for the data.
437 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
438 @param[in] IsRead Indicates it is a read or write operation.
439 @param[in] Token A pointer to the token associated with the transaction.
440 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
441 This parameter is only meaningful in async I/O request.
443 @retval EFI_SUCCESS The request is executed successfully.
444 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
445 @retval Others The request could not be executed successfully.
450 IN SD_DEVICE
*Device
,
455 IN EFI_BLOCK_IO2_TOKEN
*Token
,
460 SD_REQUEST
*RwMultiBlkReq
;
461 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
464 RwMultiBlkReq
= NULL
;
466 PassThru
= Device
->Private
->PassThru
;
468 RwMultiBlkReq
= AllocateZeroPool (sizeof (SD_REQUEST
));
469 if (RwMultiBlkReq
== NULL
) {
470 Status
= EFI_OUT_OF_RESOURCES
;
474 RwMultiBlkReq
->Signature
= SD_REQUEST_SIGNATURE
;
475 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
476 InsertTailList (&Device
->Queue
, &RwMultiBlkReq
->Link
);
477 gBS
->RestoreTPL (OldTpl
);
478 RwMultiBlkReq
->Packet
.SdMmcCmdBlk
= &RwMultiBlkReq
->SdMmcCmdBlk
;
479 RwMultiBlkReq
->Packet
.SdMmcStatusBlk
= &RwMultiBlkReq
->SdMmcStatusBlk
;
481 // Calculate timeout value through the below formula.
482 // Timeout = (transfer size) / (2MB/s).
483 // Taking 2MB/s as divisor as it's the lowest transfer speed
485 // Refer to SD Physical Layer Simplified spec section 3.4 for details.
487 RwMultiBlkReq
->Packet
.Timeout
= (BufferSize
/ (2 * 1024 * 1024) + 1) * 1000 * 1000;
490 RwMultiBlkReq
->Packet
.InDataBuffer
= Buffer
;
491 RwMultiBlkReq
->Packet
.InTransferLength
= (UINT32
)BufferSize
;
493 RwMultiBlkReq
->SdMmcCmdBlk
.CommandIndex
= SD_READ_MULTIPLE_BLOCK
;
494 RwMultiBlkReq
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAdtc
;
495 RwMultiBlkReq
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
497 RwMultiBlkReq
->Packet
.OutDataBuffer
= Buffer
;
498 RwMultiBlkReq
->Packet
.OutTransferLength
= (UINT32
)BufferSize
;
500 RwMultiBlkReq
->SdMmcCmdBlk
.CommandIndex
= SD_WRITE_MULTIPLE_BLOCK
;
501 RwMultiBlkReq
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAdtc
;
502 RwMultiBlkReq
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
505 if (Device
->SectorAddressing
) {
506 RwMultiBlkReq
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)Lba
;
508 RwMultiBlkReq
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)MultU64x32 (Lba
, Device
->BlockMedia
.BlockSize
);
511 RwMultiBlkReq
->IsEnd
= IsEnd
;
512 RwMultiBlkReq
->Token
= Token
;
514 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
515 Status
= gBS
->CreateEvent (
520 &RwMultiBlkReq
->Event
522 if (EFI_ERROR (Status
)) {
526 RwMultiBlkReq
->Event
= NULL
;
529 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &RwMultiBlkReq
->Packet
, RwMultiBlkReq
->Event
);
532 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
534 // For asynchronous operation, only free request and event in error case.
535 // The request and event will be freed in asynchronous callback for success case.
537 if (EFI_ERROR (Status
) && (RwMultiBlkReq
!= NULL
)) {
538 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
539 RemoveEntryList (&RwMultiBlkReq
->Link
);
540 gBS
->RestoreTPL (OldTpl
);
541 if (RwMultiBlkReq
->Event
!= NULL
) {
542 gBS
->CloseEvent (RwMultiBlkReq
->Event
);
544 FreePool (RwMultiBlkReq
);
548 // For synchronous operation, free request whatever the execution result is.
550 if (RwMultiBlkReq
!= NULL
) {
551 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
552 RemoveEntryList (&RwMultiBlkReq
->Link
);
553 gBS
->RestoreTPL (OldTpl
);
554 FreePool (RwMultiBlkReq
);
562 This function transfers data from/to the sd memory card device.
564 @param[in] Device A pointer to the SD_DEVICE instance.
565 @param[in] MediaId The media ID that the read/write request is for.
566 @param[in] Lba The starting logical block address to be read/written.
567 The caller is responsible for reading/writing to only
568 legitimate locations.
569 @param[in, out] Buffer A pointer to the destination/source buffer for the data.
570 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
571 @param[in] IsRead Indicates it is a read or write operation.
572 @param[in, out] Token A pointer to the token associated with the transaction.
574 @retval EFI_SUCCESS The data was read/written correctly to the device.
575 @retval EFI_WRITE_PROTECTED The device can not be read/written to.
576 @retval EFI_DEVICE_ERROR The device reported an error while performing the read/write.
577 @retval EFI_NO_MEDIA There is no media in the device.
578 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
579 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
580 @retval EFI_INVALID_PARAMETER The read/write request contains LBAs that are not valid,
581 or the buffer is not on proper alignment.
586 IN SD_DEVICE
*Device
,
592 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
596 EFI_BLOCK_IO_MEDIA
*Media
;
604 Status
= EFI_SUCCESS
;
605 Media
= &Device
->BlockMedia
;
608 if (MediaId
!= Media
->MediaId
) {
609 return EFI_MEDIA_CHANGED
;
612 if (!IsRead
&& Media
->ReadOnly
) {
613 return EFI_WRITE_PROTECTED
;
619 if (Buffer
== NULL
) {
620 return EFI_INVALID_PARAMETER
;
623 if (BufferSize
== 0) {
624 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
625 Token
->TransactionStatus
= EFI_SUCCESS
;
626 gBS
->SignalEvent (Token
->Event
);
631 BlockSize
= Media
->BlockSize
;
632 if ((BufferSize
% BlockSize
) != 0) {
633 return EFI_BAD_BUFFER_SIZE
;
636 BlockNum
= BufferSize
/ BlockSize
;
637 if ((Lba
+ BlockNum
- 1) > Media
->LastBlock
) {
638 return EFI_INVALID_PARAMETER
;
641 IoAlign
= Media
->IoAlign
;
642 if (IoAlign
> 0 && (((UINTN
) Buffer
& (IoAlign
- 1)) != 0)) {
643 return EFI_INVALID_PARAMETER
;
646 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
647 Token
->TransactionStatus
= EFI_SUCCESS
;
651 // Start to execute data transfer. The max block number in single cmd is 65535 blocks.
653 Remaining
= BlockNum
;
656 while (Remaining
> 0) {
657 if (Remaining
<= MaxBlock
) {
658 BlockNum
= Remaining
;
664 BufferSize
= BlockNum
* BlockSize
;
666 Status
= SdRwSingleBlock (Device
, Lba
, Buffer
, BufferSize
, IsRead
, Token
, LastRw
);
668 Status
= SdRwMultiBlocks (Device
, Lba
, Buffer
, BufferSize
, IsRead
, Token
, LastRw
);
670 if (EFI_ERROR (Status
)) {
673 DEBUG ((DEBUG_BLKIO
, "Sd%a(): Lba 0x%x BlkNo 0x%x Event %p with %r\n",
674 IsRead
? "Read" : "Write", Lba
, BlockNum
,
675 (Token
!= NULL
) ? Token
->Event
: NULL
, Status
));
677 Buffer
= (UINT8
*)Buffer
+ BufferSize
;
678 Remaining
-= BlockNum
;
685 Reset the Block Device.
687 @param This Indicates a pointer to the calling context.
688 @param ExtendedVerification Driver may perform diagnostics on reset.
690 @retval EFI_SUCCESS The device was reset.
691 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
698 IN EFI_BLOCK_IO_PROTOCOL
*This
,
699 IN BOOLEAN ExtendedVerification
704 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
706 Device
= SD_DEVICE_DATA_FROM_BLKIO (This
);
708 PassThru
= Device
->Private
->PassThru
;
709 Status
= PassThru
->ResetDevice (PassThru
, Device
->Slot
);
710 if (EFI_ERROR (Status
)) {
711 Status
= EFI_DEVICE_ERROR
;
718 Read BufferSize bytes from Lba into Buffer.
720 @param This Indicates a pointer to the calling context.
721 @param MediaId Id of the media, changes every time the media is replaced.
722 @param Lba The starting Logical Block Address to read from
723 @param BufferSize Size of Buffer, must be a multiple of device block size.
724 @param Buffer A pointer to the destination buffer for the data. The caller is
725 responsible for either having implicit or explicit ownership of the buffer.
727 @retval EFI_SUCCESS The data was read correctly from the device.
728 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
729 @retval EFI_NO_MEDIA There is no media in the device.
730 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
731 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
732 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
733 or the buffer is not on proper alignment.
739 IN EFI_BLOCK_IO_PROTOCOL
*This
,
749 Device
= SD_DEVICE_DATA_FROM_BLKIO (This
);
751 Status
= SdReadWrite (Device
, MediaId
, Lba
, Buffer
, BufferSize
, TRUE
, NULL
);
756 Write BufferSize bytes from Lba into Buffer.
758 @param This Indicates a pointer to the calling context.
759 @param MediaId The media ID that the write request is for.
760 @param Lba The starting logical block address to be written. The caller is
761 responsible for writing to only legitimate locations.
762 @param BufferSize Size of Buffer, must be a multiple of device block size.
763 @param Buffer A pointer to the source buffer for the data.
765 @retval EFI_SUCCESS The data was written correctly to the device.
766 @retval EFI_WRITE_PROTECTED The device can not be written to.
767 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
768 @retval EFI_NO_MEDIA There is no media in the device.
769 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
770 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
771 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
772 or the buffer is not on proper alignment.
778 IN EFI_BLOCK_IO_PROTOCOL
*This
,
788 Device
= SD_DEVICE_DATA_FROM_BLKIO (This
);
790 Status
= SdReadWrite (Device
, MediaId
, Lba
, Buffer
, BufferSize
, FALSE
, NULL
);
795 Flush the Block Device.
797 @param This Indicates a pointer to the calling context.
799 @retval EFI_SUCCESS All outstanding data was written to the device
800 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data
801 @retval EFI_NO_MEDIA There is no media in the device.
807 IN EFI_BLOCK_IO_PROTOCOL
*This
817 Reset the Block Device.
819 @param[in] This Indicates a pointer to the calling context.
820 @param[in] ExtendedVerification Driver may perform diagnostics on reset.
822 @retval EFI_SUCCESS The device was reset.
823 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
830 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
831 IN BOOLEAN ExtendedVerification
836 LIST_ENTRY
*NextLink
;
840 Device
= SD_DEVICE_DATA_FROM_BLKIO2 (This
);
842 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
843 for (Link
= GetFirstNode (&Device
->Queue
);
844 !IsNull (&Device
->Queue
, Link
);
846 NextLink
= GetNextNode (&Device
->Queue
, Link
);
847 RemoveEntryList (Link
);
849 Request
= SD_REQUEST_FROM_LINK (Link
);
851 gBS
->CloseEvent (Request
->Event
);
852 Request
->Token
->TransactionStatus
= EFI_ABORTED
;
854 if (Request
->IsEnd
) {
855 gBS
->SignalEvent (Request
->Token
->Event
);
860 gBS
->RestoreTPL (OldTpl
);
866 Read BufferSize bytes from Lba into Buffer.
868 @param[in] This Indicates a pointer to the calling context.
869 @param[in] MediaId Id of the media, changes every time the media is replaced.
870 @param[in] Lba The starting Logical Block Address to read from.
871 @param[in, out] Token A pointer to the token associated with the transaction.
872 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
873 @param[out] Buffer A pointer to the destination buffer for the data. The caller is
874 responsible for either having implicit or explicit ownership of the buffer.
876 @retval EFI_SUCCESS The read request was queued if Event is not NULL.
877 The data was read correctly from the device if
879 @retval EFI_DEVICE_ERROR The device reported an error while performing
881 @retval EFI_NO_MEDIA There is no media in the device.
882 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
883 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the
884 intrinsic block size of the device.
885 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
886 or the buffer is not on proper alignment.
887 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
894 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
897 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
905 Device
= SD_DEVICE_DATA_FROM_BLKIO2 (This
);
907 Status
= SdReadWrite (Device
, MediaId
, Lba
, Buffer
, BufferSize
, TRUE
, Token
);
912 Write BufferSize bytes from Lba into Buffer.
914 @param[in] This Indicates a pointer to the calling context.
915 @param[in] MediaId The media ID that the write request is for.
916 @param[in] Lba The starting logical block address to be written. The
917 caller is responsible for writing to only legitimate
919 @param[in, out] Token A pointer to the token associated with the transaction.
920 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
921 @param[in] Buffer A pointer to the source buffer for the data.
923 @retval EFI_SUCCESS The data was written correctly to the device.
924 @retval EFI_WRITE_PROTECTED The device can not be written to.
925 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
926 @retval EFI_NO_MEDIA There is no media in the device.
927 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
928 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
929 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
930 or the buffer is not on proper alignment.
936 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
939 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
947 Device
= SD_DEVICE_DATA_FROM_BLKIO2 (This
);
949 Status
= SdReadWrite (Device
, MediaId
, Lba
, Buffer
, BufferSize
, FALSE
, Token
);
954 Flush the Block Device.
956 @param[in] This Indicates a pointer to the calling context.
957 @param[in, out] Token A pointer to the token associated with the transaction.
959 @retval EFI_SUCCESS All outstanding data was written to the device
960 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data
961 @retval EFI_NO_MEDIA There is no media in the device.
967 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
968 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
972 // Signal event and return directly.
974 if (Token
!= NULL
&& Token
->Event
!= NULL
) {
975 Token
->TransactionStatus
= EFI_SUCCESS
;
976 gBS
->SignalEvent (Token
->Event
);
983 Set the erase start address through sync or async I/O request.
985 @param[in] Device A pointer to the SD_DEVICE instance.
986 @param[in] StartLba The starting logical block address to be erased.
987 @param[in] Token A pointer to the token associated with the transaction.
988 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
989 This parameter is only meaningful in async I/O request.
991 @retval EFI_SUCCESS The request is executed successfully.
992 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
993 @retval Others The request could not be executed successfully.
998 IN SD_DEVICE
*Device
,
1000 IN EFI_BLOCK_IO2_TOKEN
*Token
,
1005 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
1006 SD_REQUEST
*EraseBlockStart
;
1009 EraseBlockStart
= NULL
;
1010 PassThru
= Device
->Private
->PassThru
;
1012 EraseBlockStart
= AllocateZeroPool (sizeof (SD_REQUEST
));
1013 if (EraseBlockStart
== NULL
) {
1014 Status
= EFI_OUT_OF_RESOURCES
;
1018 EraseBlockStart
->Signature
= SD_REQUEST_SIGNATURE
;
1019 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1020 InsertTailList (&Device
->Queue
, &EraseBlockStart
->Link
);
1021 gBS
->RestoreTPL (OldTpl
);
1022 EraseBlockStart
->Packet
.SdMmcCmdBlk
= &EraseBlockStart
->SdMmcCmdBlk
;
1023 EraseBlockStart
->Packet
.SdMmcStatusBlk
= &EraseBlockStart
->SdMmcStatusBlk
;
1024 EraseBlockStart
->Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
1026 EraseBlockStart
->SdMmcCmdBlk
.CommandIndex
= SD_ERASE_WR_BLK_START
;
1027 EraseBlockStart
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
1028 EraseBlockStart
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
1030 if (Device
->SectorAddressing
) {
1031 EraseBlockStart
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)StartLba
;
1033 EraseBlockStart
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)MultU64x32 (StartLba
, Device
->BlockMedia
.BlockSize
);
1036 EraseBlockStart
->IsEnd
= IsEnd
;
1037 EraseBlockStart
->Token
= Token
;
1039 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1040 Status
= gBS
->CreateEvent (
1045 &EraseBlockStart
->Event
1047 if (EFI_ERROR (Status
)) {
1051 EraseBlockStart
->Event
= NULL
;
1054 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &EraseBlockStart
->Packet
, EraseBlockStart
->Event
);
1057 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1059 // For asynchronous operation, only free request and event in error case.
1060 // The request and event will be freed in asynchronous callback for success case.
1062 if (EFI_ERROR (Status
) && (EraseBlockStart
!= NULL
)) {
1063 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1064 RemoveEntryList (&EraseBlockStart
->Link
);
1065 gBS
->RestoreTPL (OldTpl
);
1066 if (EraseBlockStart
->Event
!= NULL
) {
1067 gBS
->CloseEvent (EraseBlockStart
->Event
);
1069 FreePool (EraseBlockStart
);
1073 // For synchronous operation, free request whatever the execution result is.
1075 if (EraseBlockStart
!= NULL
) {
1076 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1077 RemoveEntryList (&EraseBlockStart
->Link
);
1078 gBS
->RestoreTPL (OldTpl
);
1079 FreePool (EraseBlockStart
);
1087 Set the erase end address through sync or async I/O request.
1089 @param[in] Device A pointer to the SD_DEVICE instance.
1090 @param[in] EndLba The ending logical block address to be erased.
1091 @param[in] Token A pointer to the token associated with the transaction.
1092 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
1093 This parameter is only meaningful in async I/O request.
1095 @retval EFI_SUCCESS The request is executed successfully.
1096 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
1097 @retval Others The request could not be executed successfully.
1102 IN SD_DEVICE
*Device
,
1104 IN EFI_BLOCK_IO2_TOKEN
*Token
,
1109 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
1110 SD_REQUEST
*EraseBlockEnd
;
1113 EraseBlockEnd
= NULL
;
1114 PassThru
= Device
->Private
->PassThru
;
1116 EraseBlockEnd
= AllocateZeroPool (sizeof (SD_REQUEST
));
1117 if (EraseBlockEnd
== NULL
) {
1118 Status
= EFI_OUT_OF_RESOURCES
;
1122 EraseBlockEnd
->Signature
= SD_REQUEST_SIGNATURE
;
1123 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1124 InsertTailList (&Device
->Queue
, &EraseBlockEnd
->Link
);
1125 gBS
->RestoreTPL (OldTpl
);
1126 EraseBlockEnd
->Packet
.SdMmcCmdBlk
= &EraseBlockEnd
->SdMmcCmdBlk
;
1127 EraseBlockEnd
->Packet
.SdMmcStatusBlk
= &EraseBlockEnd
->SdMmcStatusBlk
;
1128 EraseBlockEnd
->Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
1130 EraseBlockEnd
->SdMmcCmdBlk
.CommandIndex
= SD_ERASE_WR_BLK_END
;
1131 EraseBlockEnd
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
1132 EraseBlockEnd
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
1134 if (Device
->SectorAddressing
) {
1135 EraseBlockEnd
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)EndLba
;
1137 EraseBlockEnd
->SdMmcCmdBlk
.CommandArgument
= (UINT32
)MultU64x32 (EndLba
, Device
->BlockMedia
.BlockSize
);
1140 EraseBlockEnd
->IsEnd
= IsEnd
;
1141 EraseBlockEnd
->Token
= Token
;
1143 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1144 Status
= gBS
->CreateEvent (
1149 &EraseBlockEnd
->Event
1151 if (EFI_ERROR (Status
)) {
1155 EraseBlockEnd
->Event
= NULL
;
1158 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &EraseBlockEnd
->Packet
, EraseBlockEnd
->Event
);
1161 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1163 // For asynchronous operation, only free request and event in error case.
1164 // The request and event will be freed in asynchronous callback for success case.
1166 if (EFI_ERROR (Status
) && (EraseBlockEnd
!= NULL
)) {
1167 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1168 RemoveEntryList (&EraseBlockEnd
->Link
);
1169 gBS
->RestoreTPL (OldTpl
);
1170 if (EraseBlockEnd
->Event
!= NULL
) {
1171 gBS
->CloseEvent (EraseBlockEnd
->Event
);
1173 FreePool (EraseBlockEnd
);
1177 // For synchronous operation, free request whatever the execution result is.
1179 if (EraseBlockEnd
!= NULL
) {
1180 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1181 RemoveEntryList (&EraseBlockEnd
->Link
);
1182 gBS
->RestoreTPL (OldTpl
);
1183 FreePool (EraseBlockEnd
);
1191 Erase specified blocks through sync or async I/O request.
1193 @param[in] Device A pointer to the SD_DEVICE instance.
1194 @param[in] Token A pointer to the token associated with the transaction.
1195 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
1196 This parameter is only meaningful in async I/O request.
1198 @retval EFI_SUCCESS The request is executed successfully.
1199 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
1200 @retval Others The request could not be executed successfully.
1205 IN SD_DEVICE
*Device
,
1206 IN EFI_BLOCK_IO2_TOKEN
*Token
,
1211 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
1212 SD_REQUEST
*EraseBlock
;
1216 PassThru
= Device
->Private
->PassThru
;
1218 EraseBlock
= AllocateZeroPool (sizeof (SD_REQUEST
));
1219 if (EraseBlock
== NULL
) {
1220 Status
= EFI_OUT_OF_RESOURCES
;
1224 EraseBlock
->Signature
= SD_REQUEST_SIGNATURE
;
1225 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1226 InsertTailList (&Device
->Queue
, &EraseBlock
->Link
);
1227 gBS
->RestoreTPL (OldTpl
);
1228 EraseBlock
->Packet
.SdMmcCmdBlk
= &EraseBlock
->SdMmcCmdBlk
;
1229 EraseBlock
->Packet
.SdMmcStatusBlk
= &EraseBlock
->SdMmcStatusBlk
;
1230 EraseBlock
->Packet
.Timeout
= SD_GENERIC_TIMEOUT
;
1232 EraseBlock
->SdMmcCmdBlk
.CommandIndex
= SD_ERASE
;
1233 EraseBlock
->SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
1234 EraseBlock
->SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1b
;
1236 EraseBlock
->IsEnd
= IsEnd
;
1237 EraseBlock
->Token
= Token
;
1239 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1240 Status
= gBS
->CreateEvent (
1247 if (EFI_ERROR (Status
)) {
1251 EraseBlock
->Event
= NULL
;
1254 Status
= PassThru
->PassThru (PassThru
, Device
->Slot
, &EraseBlock
->Packet
, EraseBlock
->Event
);
1257 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1259 // For asynchronous operation, only free request and event in error case.
1260 // The request and event will be freed in asynchronous callback for success case.
1262 if (EFI_ERROR (Status
) && (EraseBlock
!= NULL
)) {
1263 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1264 RemoveEntryList (&EraseBlock
->Link
);
1265 gBS
->RestoreTPL (OldTpl
);
1266 if (EraseBlock
->Event
!= NULL
) {
1267 gBS
->CloseEvent (EraseBlock
->Event
);
1269 FreePool (EraseBlock
);
1273 // For synchronous operation, free request whatever the execution result is.
1275 if (EraseBlock
!= NULL
) {
1276 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1277 RemoveEntryList (&EraseBlock
->Link
);
1278 gBS
->RestoreTPL (OldTpl
);
1279 FreePool (EraseBlock
);
1287 Erase a specified number of device blocks.
1289 @param[in] This Indicates a pointer to the calling context.
1290 @param[in] MediaId The media ID that the erase request is for.
1291 @param[in] Lba The starting logical block address to be
1292 erased. The caller is responsible for erasing
1293 only legitimate locations.
1294 @param[in, out] Token A pointer to the token associated with the
1296 @param[in] Size The size in bytes to be erased. This must be
1297 a multiple of the physical block size of the
1300 @retval EFI_SUCCESS The erase request was queued if Event is not
1301 NULL. The data was erased correctly to the
1302 device if the Event is NULL.to the device.
1303 @retval EFI_WRITE_PROTECTED The device cannot be erased due to write
1305 @retval EFI_DEVICE_ERROR The device reported an error while attempting
1306 to perform the erase operation.
1307 @retval EFI_INVALID_PARAMETER The erase request contains LBAs that are not
1309 @retval EFI_NO_MEDIA There is no media in the device.
1310 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1316 IN EFI_ERASE_BLOCK_PROTOCOL
*This
,
1319 IN OUT EFI_ERASE_BLOCK_TOKEN
*Token
,
1324 EFI_BLOCK_IO_MEDIA
*Media
;
1330 Status
= EFI_SUCCESS
;
1331 Device
= SD_DEVICE_DATA_FROM_ERASEBLK (This
);
1332 Media
= &Device
->BlockMedia
;
1334 if (MediaId
!= Media
->MediaId
) {
1335 return EFI_MEDIA_CHANGED
;
1338 if (Media
->ReadOnly
) {
1339 return EFI_WRITE_PROTECTED
;
1343 // Check parameters.
1345 BlockSize
= Media
->BlockSize
;
1346 if ((Size
% BlockSize
) != 0) {
1347 return EFI_INVALID_PARAMETER
;
1350 BlockNum
= Size
/ BlockSize
;
1351 if ((Lba
+ BlockNum
- 1) > Media
->LastBlock
) {
1352 return EFI_INVALID_PARAMETER
;
1355 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1356 Token
->TransactionStatus
= EFI_SUCCESS
;
1359 LastLba
= Lba
+ BlockNum
- 1;
1361 Status
= SdEraseBlockStart (Device
, Lba
, (EFI_BLOCK_IO2_TOKEN
*)Token
, FALSE
);
1362 if (EFI_ERROR (Status
)) {
1366 Status
= SdEraseBlockEnd (Device
, LastLba
, (EFI_BLOCK_IO2_TOKEN
*)Token
, FALSE
);
1367 if (EFI_ERROR (Status
)) {
1371 Status
= SdEraseBlock (Device
, (EFI_BLOCK_IO2_TOKEN
*)Token
, TRUE
);
1372 if (EFI_ERROR (Status
)) {
1376 DEBUG ((EFI_D_ERROR
, "SdEraseBlocks(): Lba 0x%x BlkNo 0x%x Event %p with %r\n", Lba
, BlockNum
, Token
->Event
, Status
));