TianoCore EDK2 master
Loading...
Searching...
No Matches
EmmcBlockIo.c
Go to the documentation of this file.
1
9#include "EmmcDxe.h"
10
19VOID
20EFIAPI
22 IN EFI_EVENT Event,
23 IN VOID *Context
24 )
25{
26 EMMC_REQUEST *Request;
27 EFI_STATUS Status;
28
29 Status = gBS->CloseEvent (Event);
30 if (EFI_ERROR (Status)) {
31 return;
32 }
33
34 Request = (EMMC_REQUEST *)Context;
35
37 DEBUG ((
38 DEBUG_INFO,
39 "Emmc Async Request: CmdIndex[%d] Arg[%08x] %r\n",
40 Request->SdMmcCmdBlk.CommandIndex,
41 Request->SdMmcCmdBlk.CommandArgument,
42 Request->Packet.TransactionStatus
43 ));
45
46 if (EFI_ERROR (Request->Packet.TransactionStatus)) {
47 Request->Token->TransactionStatus = Request->Packet.TransactionStatus;
48 }
49
50 RemoveEntryList (&Request->Link);
51
52 if (Request->IsEnd) {
53 gBS->SignalEvent (Request->Token->Event);
54 }
55
56 FreePool (Request);
57}
58
72 IN EMMC_DEVICE *Device,
73 IN UINT16 Rca
74 )
75{
76 EFI_STATUS Status;
78 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
79 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
81
82 PassThru = Device->Private->PassThru;
83
84 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
85 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
86 ZeroMem (&Packet, sizeof (Packet));
87 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
88 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
89 Packet.Timeout = EMMC_GENERIC_TIMEOUT;
90
91 SdMmcCmdBlk.CommandIndex = EMMC_SELECT_DESELECT_CARD;
92 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
93 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
94 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
95
96 Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL);
97
98 return Status;
99}
100
115 IN EMMC_DEVICE *Device,
116 IN UINT16 Rca,
117 OUT UINT32 *DevStatus
118 )
119{
120 EFI_STATUS Status;
122 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
123 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
125
126 PassThru = Device->Private->PassThru;
127
128 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
129 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
130 ZeroMem (&Packet, sizeof (Packet));
131 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
132 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
133 Packet.Timeout = EMMC_GENERIC_TIMEOUT;
134
135 SdMmcCmdBlk.CommandIndex = EMMC_SEND_STATUS;
136 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
137 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
138 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
139
140 Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL);
141 if (!EFI_ERROR (Status)) {
142 CopyMem (DevStatus, &SdMmcStatusBlk.Resp0, sizeof (UINT32));
143 }
144
145 return Status;
146}
147
162 IN EMMC_DEVICE *Device,
163 IN UINT16 Rca,
164 OUT EMMC_CSD *Csd
165 )
166{
167 EFI_STATUS Status;
169 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
170 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
172
173 PassThru = Device->Private->PassThru;
174
175 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
176 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
177 ZeroMem (&Packet, sizeof (Packet));
178 ZeroMem (Csd, sizeof (EMMC_CSD));
179
180 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
181 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
182 Packet.Timeout = EMMC_GENERIC_TIMEOUT;
183
184 SdMmcCmdBlk.CommandIndex = EMMC_SEND_CSD;
185 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
186 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;
187 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
188
189 Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL);
190 if (!EFI_ERROR (Status)) {
191 //
192 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
193 //
194 CopyMem (((UINT8 *)Csd) + 1, &SdMmcStatusBlk.Resp0, sizeof (EMMC_CSD) - 1);
195 }
196
197 return Status;
198}
199
214 IN EMMC_DEVICE *Device,
215 IN UINT16 Rca,
216 OUT EMMC_CID *Cid
217 )
218{
219 EFI_STATUS Status;
221 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
222 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
224
225 PassThru = Device->Private->PassThru;
226
227 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
228 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
229 ZeroMem (&Packet, sizeof (Packet));
230 ZeroMem (Cid, sizeof (EMMC_CID));
231
232 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
233 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
234 Packet.Timeout = EMMC_GENERIC_TIMEOUT;
235
236 SdMmcCmdBlk.CommandIndex = EMMC_SEND_CID;
237 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
238 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;
239 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
240
241 Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL);
242 if (!EFI_ERROR (Status)) {
243 //
244 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
245 //
246 CopyMem (((UINT8 *)Cid) + 1, &SdMmcStatusBlk.Resp0, sizeof (EMMC_CID) - 1);
247 }
248
249 return Status;
250}
251
265 IN EMMC_DEVICE *Device,
266 OUT EMMC_EXT_CSD *ExtCsd
267 )
268{
269 EFI_STATUS Status;
271 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
272 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
274
275 PassThru = Device->Private->PassThru;
276
277 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
278 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
279 ZeroMem (&Packet, sizeof (Packet));
280 ZeroMem (ExtCsd, sizeof (EMMC_EXT_CSD));
281 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
282 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
283 Packet.Timeout = EMMC_GENERIC_TIMEOUT;
284
285 SdMmcCmdBlk.CommandIndex = EMMC_SEND_EXT_CSD;
286 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;
287 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
288 SdMmcCmdBlk.CommandArgument = 0x00000000;
289 Packet.InDataBuffer = ExtCsd;
290 Packet.InTransferLength = sizeof (EMMC_EXT_CSD);
291
292 Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL);
293
294 return Status;
295}
296
314 IN EMMC_PARTITION *Partition,
315 IN UINT8 Offset,
316 IN UINT8 Value,
317 IN EFI_BLOCK_IO2_TOKEN *Token,
318 IN BOOLEAN IsEnd
319 )
320{
321 EFI_STATUS Status;
322 EMMC_DEVICE *Device;
323 EMMC_REQUEST *SetExtCsdReq;
325 UINT32 CommandArgument;
326 EFI_TPL OldTpl;
327
328 SetExtCsdReq = NULL;
329
330 Device = Partition->Device;
331 PassThru = Device->Private->PassThru;
332
333 SetExtCsdReq = AllocateZeroPool (sizeof (EMMC_REQUEST));
334 if (SetExtCsdReq == NULL) {
335 Status = EFI_OUT_OF_RESOURCES;
336 goto Error;
337 }
338
339 SetExtCsdReq->Signature = EMMC_REQUEST_SIGNATURE;
340 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
341 InsertTailList (&Partition->Queue, &SetExtCsdReq->Link);
342 gBS->RestoreTPL (OldTpl);
343 SetExtCsdReq->Packet.SdMmcCmdBlk = &SetExtCsdReq->SdMmcCmdBlk;
344 SetExtCsdReq->Packet.SdMmcStatusBlk = &SetExtCsdReq->SdMmcStatusBlk;
345 SetExtCsdReq->Packet.Timeout = EMMC_GENERIC_TIMEOUT;
346
347 SetExtCsdReq->SdMmcCmdBlk.CommandIndex = EMMC_SWITCH;
348 SetExtCsdReq->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
349 SetExtCsdReq->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b;
350 //
351 // Write the Value to the field specified by Offset.
352 //
353 CommandArgument = (Value << 8) | (Offset << 16) | BIT24 | BIT25;
354 SetExtCsdReq->SdMmcCmdBlk.CommandArgument = CommandArgument;
355
356 SetExtCsdReq->IsEnd = IsEnd;
357 SetExtCsdReq->Token = Token;
358
359 if ((Token != NULL) && (Token->Event != NULL)) {
360 Status = gBS->CreateEvent (
361 EVT_NOTIFY_SIGNAL,
362 TPL_NOTIFY,
364 SetExtCsdReq,
365 &SetExtCsdReq->Event
366 );
367 if (EFI_ERROR (Status)) {
368 goto Error;
369 }
370 } else {
371 SetExtCsdReq->Event = NULL;
372 }
373
374 Status = PassThru->PassThru (PassThru, Device->Slot, &SetExtCsdReq->Packet, SetExtCsdReq->Event);
375
376Error:
377 if ((Token != NULL) && (Token->Event != NULL)) {
378 //
379 // For asynchronous operation, only free request and event in error case.
380 // The request and event will be freed in asynchronous callback for success case.
381 //
382 if (EFI_ERROR (Status) && (SetExtCsdReq != NULL)) {
383 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
384 RemoveEntryList (&SetExtCsdReq->Link);
385 gBS->RestoreTPL (OldTpl);
386 if (SetExtCsdReq->Event != NULL) {
387 gBS->CloseEvent (SetExtCsdReq->Event);
388 }
389
390 FreePool (SetExtCsdReq);
391 }
392 } else {
393 //
394 // For synchronous operation, free request whatever the execution result is.
395 //
396 if (SetExtCsdReq != NULL) {
397 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
398 RemoveEntryList (&SetExtCsdReq->Link);
399 gBS->RestoreTPL (OldTpl);
400 FreePool (SetExtCsdReq);
401 }
402 }
403
404 return Status;
405}
406
423 IN EMMC_PARTITION *Partition,
424 IN UINT16 BlockNum,
425 IN EFI_BLOCK_IO2_TOKEN *Token,
426 IN BOOLEAN IsEnd
427 )
428{
429 EFI_STATUS Status;
430 EMMC_DEVICE *Device;
431 EMMC_REQUEST *SetBlkCntReq;
433 EFI_TPL OldTpl;
434
435 SetBlkCntReq = NULL;
436
437 Device = Partition->Device;
438 PassThru = Device->Private->PassThru;
439
440 SetBlkCntReq = AllocateZeroPool (sizeof (EMMC_REQUEST));
441 if (SetBlkCntReq == NULL) {
442 Status = EFI_OUT_OF_RESOURCES;
443 goto Error;
444 }
445
446 SetBlkCntReq->Signature = EMMC_REQUEST_SIGNATURE;
447 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
448 InsertTailList (&Partition->Queue, &SetBlkCntReq->Link);
449 gBS->RestoreTPL (OldTpl);
450 SetBlkCntReq->Packet.SdMmcCmdBlk = &SetBlkCntReq->SdMmcCmdBlk;
451 SetBlkCntReq->Packet.SdMmcStatusBlk = &SetBlkCntReq->SdMmcStatusBlk;
452 SetBlkCntReq->Packet.Timeout = EMMC_GENERIC_TIMEOUT;
453
454 SetBlkCntReq->SdMmcCmdBlk.CommandIndex = EMMC_SET_BLOCK_COUNT;
455 SetBlkCntReq->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
456 SetBlkCntReq->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
457 SetBlkCntReq->SdMmcCmdBlk.CommandArgument = BlockNum;
458
459 SetBlkCntReq->IsEnd = IsEnd;
460 SetBlkCntReq->Token = Token;
461
462 if ((Token != NULL) && (Token->Event != NULL)) {
463 Status = gBS->CreateEvent (
464 EVT_NOTIFY_SIGNAL,
465 TPL_NOTIFY,
467 SetBlkCntReq,
468 &SetBlkCntReq->Event
469 );
470 if (EFI_ERROR (Status)) {
471 goto Error;
472 }
473 } else {
474 SetBlkCntReq->Event = NULL;
475 }
476
477 Status = PassThru->PassThru (PassThru, Device->Slot, &SetBlkCntReq->Packet, SetBlkCntReq->Event);
478
479Error:
480 if ((Token != NULL) && (Token->Event != NULL)) {
481 //
482 // For asynchronous operation, only free request and event in error case.
483 // The request and event will be freed in asynchronous callback for success case.
484 //
485 if (EFI_ERROR (Status) && (SetBlkCntReq != NULL)) {
486 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
487 RemoveEntryList (&SetBlkCntReq->Link);
488 gBS->RestoreTPL (OldTpl);
489 if (SetBlkCntReq->Event != NULL) {
490 gBS->CloseEvent (SetBlkCntReq->Event);
491 }
492
493 FreePool (SetBlkCntReq);
494 }
495 } else {
496 //
497 // For synchronous operation, free request whatever the execution result is.
498 //
499 if (SetBlkCntReq != NULL) {
500 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
501 RemoveEntryList (&SetBlkCntReq->Link);
502 gBS->RestoreTPL (OldTpl);
503 FreePool (SetBlkCntReq);
504 }
505 }
506
507 return Status;
508}
509
536 IN EMMC_PARTITION *Partition,
537 IN UINT8 SecurityProtocol,
538 IN UINT16 SecurityProtocolSpecificData,
539 IN UINTN PayloadBufferSize,
540 OUT VOID *PayloadBuffer,
541 IN BOOLEAN IsRead,
542 IN UINT64 Timeout,
543 IN EFI_BLOCK_IO2_TOKEN *Token,
544 IN BOOLEAN IsEnd
545 )
546{
547 EFI_STATUS Status;
548 EMMC_DEVICE *Device;
549 EMMC_REQUEST *ProtocolReq;
551 EFI_TPL OldTpl;
552
553 ProtocolReq = NULL;
554
555 Device = Partition->Device;
556 PassThru = Device->Private->PassThru;
557
558 ProtocolReq = AllocateZeroPool (sizeof (EMMC_REQUEST));
559 if (ProtocolReq == NULL) {
560 Status = EFI_OUT_OF_RESOURCES;
561 goto Error;
562 }
563
564 ProtocolReq->Signature = EMMC_REQUEST_SIGNATURE;
565 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
566 InsertTailList (&Partition->Queue, &ProtocolReq->Link);
567 gBS->RestoreTPL (OldTpl);
568 ProtocolReq->Packet.SdMmcCmdBlk = &ProtocolReq->SdMmcCmdBlk;
569 ProtocolReq->Packet.SdMmcStatusBlk = &ProtocolReq->SdMmcStatusBlk;
570
571 if (IsRead) {
572 ProtocolReq->Packet.InDataBuffer = PayloadBuffer;
573 ProtocolReq->Packet.InTransferLength = (UINT32)PayloadBufferSize;
574
575 ProtocolReq->SdMmcCmdBlk.CommandIndex = EMMC_PROTOCOL_RD;
576 ProtocolReq->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;
577 ProtocolReq->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
578 } else {
579 ProtocolReq->Packet.OutDataBuffer = PayloadBuffer;
580 ProtocolReq->Packet.OutTransferLength = (UINT32)PayloadBufferSize;
581
582 ProtocolReq->SdMmcCmdBlk.CommandIndex = EMMC_PROTOCOL_WR;
583 ProtocolReq->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;
584 ProtocolReq->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
585 }
586
587 ProtocolReq->SdMmcCmdBlk.CommandArgument = (SecurityProtocol << 8) | (SecurityProtocolSpecificData << 16);
588 //
589 // Convert to 1 microsecond unit.
590 //
591 ProtocolReq->Packet.Timeout = DivU64x32 (Timeout, 10) + 1;
592
593 ProtocolReq->IsEnd = IsEnd;
594 ProtocolReq->Token = Token;
595
596 if ((Token != NULL) && (Token->Event != NULL)) {
597 Status = gBS->CreateEvent (
598 EVT_NOTIFY_SIGNAL,
599 TPL_NOTIFY,
601 ProtocolReq,
602 &ProtocolReq->Event
603 );
604 if (EFI_ERROR (Status)) {
605 goto Error;
606 }
607 } else {
608 ProtocolReq->Event = NULL;
609 }
610
611 Status = PassThru->PassThru (PassThru, Device->Slot, &ProtocolReq->Packet, ProtocolReq->Event);
612
613Error:
614 if ((Token != NULL) && (Token->Event != NULL)) {
615 //
616 // For asynchronous operation, only free request and event in error case.
617 // The request and event will be freed in asynchronous callback for success case.
618 //
619 if (EFI_ERROR (Status) && (ProtocolReq != NULL)) {
620 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
621 RemoveEntryList (&ProtocolReq->Link);
622 gBS->RestoreTPL (OldTpl);
623 if (ProtocolReq->Event != NULL) {
624 gBS->CloseEvent (ProtocolReq->Event);
625 }
626
627 FreePool (ProtocolReq);
628 }
629 } else {
630 //
631 // For synchronous operation, free request whatever the execution result is.
632 //
633 if (ProtocolReq != NULL) {
634 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
635 RemoveEntryList (&ProtocolReq->Link);
636 gBS->RestoreTPL (OldTpl);
637 FreePool (ProtocolReq);
638 }
639 }
640
641 return Status;
642}
643
665 IN EMMC_PARTITION *Partition,
666 IN EFI_LBA Lba,
667 IN VOID *Buffer,
668 IN UINTN BufferSize,
669 IN BOOLEAN IsRead,
670 IN EFI_BLOCK_IO2_TOKEN *Token,
671 IN BOOLEAN IsEnd
672 )
673{
674 EFI_STATUS Status;
675 EMMC_DEVICE *Device;
676 EMMC_REQUEST *RwMultiBlkReq;
678 EFI_TPL OldTpl;
679
680 RwMultiBlkReq = NULL;
681
682 Device = Partition->Device;
683 PassThru = Device->Private->PassThru;
684
685 RwMultiBlkReq = AllocateZeroPool (sizeof (EMMC_REQUEST));
686 if (RwMultiBlkReq == NULL) {
687 Status = EFI_OUT_OF_RESOURCES;
688 goto Error;
689 }
690
691 RwMultiBlkReq->Signature = EMMC_REQUEST_SIGNATURE;
692 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
693 InsertTailList (&Partition->Queue, &RwMultiBlkReq->Link);
694 gBS->RestoreTPL (OldTpl);
695 RwMultiBlkReq->Packet.SdMmcCmdBlk = &RwMultiBlkReq->SdMmcCmdBlk;
696 RwMultiBlkReq->Packet.SdMmcStatusBlk = &RwMultiBlkReq->SdMmcStatusBlk;
697 //
698 // Calculate timeout value through the below formula.
699 // Timeout = (transfer size) / (2MB/s).
700 // Taking 2MB/s as divisor is because it's nearest to the eMMC lowest
701 // transfer speed (2.4MB/s).
702 // Refer to eMMC 5.0 spec section 6.9.1 for details.
703 //
704 RwMultiBlkReq->Packet.Timeout = (BufferSize / (2 * 1024 * 1024) + 1) * 1000 * 1000;
705
706 if (IsRead) {
707 RwMultiBlkReq->Packet.InDataBuffer = Buffer;
708 RwMultiBlkReq->Packet.InTransferLength = (UINT32)BufferSize;
709
710 RwMultiBlkReq->SdMmcCmdBlk.CommandIndex = EMMC_READ_MULTIPLE_BLOCK;
711 RwMultiBlkReq->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;
712 RwMultiBlkReq->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
713 } else {
714 RwMultiBlkReq->Packet.OutDataBuffer = Buffer;
715 RwMultiBlkReq->Packet.OutTransferLength = (UINT32)BufferSize;
716
717 RwMultiBlkReq->SdMmcCmdBlk.CommandIndex = EMMC_WRITE_MULTIPLE_BLOCK;
718 RwMultiBlkReq->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;
719 RwMultiBlkReq->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
720 }
721
722 if (Partition->Device->SectorAddressing) {
723 RwMultiBlkReq->SdMmcCmdBlk.CommandArgument = (UINT32)Lba;
724 } else {
725 RwMultiBlkReq->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (Lba, Partition->BlockMedia.BlockSize);
726 }
727
728 RwMultiBlkReq->IsEnd = IsEnd;
729 RwMultiBlkReq->Token = Token;
730
731 if ((Token != NULL) && (Token->Event != NULL)) {
732 Status = gBS->CreateEvent (
733 EVT_NOTIFY_SIGNAL,
734 TPL_NOTIFY,
736 RwMultiBlkReq,
737 &RwMultiBlkReq->Event
738 );
739 if (EFI_ERROR (Status)) {
740 goto Error;
741 }
742 } else {
743 RwMultiBlkReq->Event = NULL;
744 }
745
746 Status = PassThru->PassThru (PassThru, Device->Slot, &RwMultiBlkReq->Packet, RwMultiBlkReq->Event);
747
748Error:
749 if ((Token != NULL) && (Token->Event != NULL)) {
750 //
751 // For asynchronous operation, only free request and event in error case.
752 // The request and event will be freed in asynchronous callback for success case.
753 //
754 if (EFI_ERROR (Status) && (RwMultiBlkReq != NULL)) {
755 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
756 RemoveEntryList (&RwMultiBlkReq->Link);
757 gBS->RestoreTPL (OldTpl);
758 if (RwMultiBlkReq->Event != NULL) {
759 gBS->CloseEvent (RwMultiBlkReq->Event);
760 }
761
762 FreePool (RwMultiBlkReq);
763 }
764 } else {
765 //
766 // For synchronous operation, free request whatever the execution result is.
767 //
768 if (RwMultiBlkReq != NULL) {
769 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
770 RemoveEntryList (&RwMultiBlkReq->Link);
771 gBS->RestoreTPL (OldTpl);
772 FreePool (RwMultiBlkReq);
773 }
774 }
775
776 return Status;
777}
778
804 IN EMMC_PARTITION *Partition,
805 IN UINT32 MediaId,
806 IN EFI_LBA Lba,
807 IN OUT VOID *Buffer,
808 IN UINTN BufferSize,
809 IN BOOLEAN IsRead,
811 )
812{
813 EFI_STATUS Status;
814 EMMC_DEVICE *Device;
815 EFI_BLOCK_IO_MEDIA *Media;
816 UINTN BlockSize;
817 UINTN BlockNum;
818 UINTN IoAlign;
819 UINT8 PartitionConfig;
820 UINTN Remaining;
821 UINT32 MaxBlock;
822 BOOLEAN LastRw;
823
824 Status = EFI_SUCCESS;
825 Device = Partition->Device;
826 Media = &Partition->BlockMedia;
827 LastRw = FALSE;
828
829 if (MediaId != Media->MediaId) {
830 return EFI_MEDIA_CHANGED;
831 }
832
833 if (!IsRead && Media->ReadOnly) {
834 return EFI_WRITE_PROTECTED;
835 }
836
837 //
838 // Check parameters.
839 //
840 if (Buffer == NULL) {
841 return EFI_INVALID_PARAMETER;
842 }
843
844 if (BufferSize == 0) {
845 if ((Token != NULL) && (Token->Event != NULL)) {
846 Token->TransactionStatus = EFI_SUCCESS;
847 gBS->SignalEvent (Token->Event);
848 }
849
850 return EFI_SUCCESS;
851 }
852
853 BlockSize = Media->BlockSize;
854 if ((BufferSize % BlockSize) != 0) {
855 return EFI_BAD_BUFFER_SIZE;
856 }
857
858 BlockNum = BufferSize / BlockSize;
859 if ((Lba + BlockNum - 1) > Media->LastBlock) {
860 return EFI_INVALID_PARAMETER;
861 }
862
863 IoAlign = Media->IoAlign;
864 if ((IoAlign > 0) && (((UINTN)Buffer & (IoAlign - 1)) != 0)) {
865 return EFI_INVALID_PARAMETER;
866 }
867
868 if ((Token != NULL) && (Token->Event != NULL)) {
869 Token->TransactionStatus = EFI_SUCCESS;
870 }
871
872 //
873 // Check if needs to switch partition access.
874 //
875 PartitionConfig = Device->ExtCsd.PartitionConfig;
876 if ((PartitionConfig & 0x7) != Partition->PartitionType) {
877 PartitionConfig &= (UINT8) ~0x7;
878 PartitionConfig |= Partition->PartitionType;
879 Status = EmmcSetExtCsd (Partition, OFFSET_OF (EMMC_EXT_CSD, PartitionConfig), PartitionConfig, Token, FALSE);
880 if (EFI_ERROR (Status)) {
881 return Status;
882 }
883
884 Device->ExtCsd.PartitionConfig = PartitionConfig;
885 }
886
887 //
888 // Start to execute data transfer. The max block number in single cmd is 65535 blocks.
889 //
890 Remaining = BlockNum;
891 MaxBlock = 0xFFFF;
892
893 while (Remaining > 0) {
894 if (Remaining <= MaxBlock) {
895 BlockNum = Remaining;
896 LastRw = TRUE;
897 } else {
898 BlockNum = MaxBlock;
899 }
900
901 Status = EmmcSetBlkCount (Partition, (UINT16)BlockNum, Token, FALSE);
902 if (EFI_ERROR (Status)) {
903 return Status;
904 }
905
906 BufferSize = BlockNum * BlockSize;
907 Status = EmmcRwMultiBlocks (Partition, Lba, Buffer, BufferSize, IsRead, Token, LastRw);
908 if (EFI_ERROR (Status)) {
909 return Status;
910 }
911
912 DEBUG ((
913 DEBUG_BLKIO,
914 "Emmc%a(): Part %d Lba 0x%x BlkNo 0x%x Event %p with %r\n",
915 IsRead ? "Read " : "Write",
916 Partition->PartitionType,
917 Lba,
918 BlockNum,
919 (Token != NULL) ? Token->Event : NULL,
920 Status
921 ));
922
923 Lba += BlockNum;
924 Buffer = (UINT8 *)Buffer + BufferSize;
925 Remaining -= BlockNum;
926 }
927
928 return Status;
929}
930
943EFIAPI
946 IN BOOLEAN ExtendedVerification
947 )
948{
949 EFI_STATUS Status;
950 EMMC_PARTITION *Partition;
952
953 Partition = EMMC_PARTITION_DATA_FROM_BLKIO (This);
954
955 PassThru = Partition->Device->Private->PassThru;
956 Status = PassThru->ResetDevice (PassThru, Partition->Device->Slot);
957 if (EFI_ERROR (Status)) {
958 Status = EFI_DEVICE_ERROR;
959 }
960
961 return Status;
962}
963
984EFIAPI
987 IN UINT32 MediaId,
988 IN EFI_LBA Lba,
989 IN UINTN BufferSize,
990 OUT VOID *Buffer
991 )
992{
993 EFI_STATUS Status;
994 EMMC_PARTITION *Partition;
995
996 Partition = EMMC_PARTITION_DATA_FROM_BLKIO (This);
997
998 Status = EmmcReadWrite (Partition, MediaId, Lba, Buffer, BufferSize, TRUE, NULL);
999 return Status;
1000}
1001
1023EFIAPI
1026 IN UINT32 MediaId,
1027 IN EFI_LBA Lba,
1028 IN UINTN BufferSize,
1029 IN VOID *Buffer
1030 )
1031{
1032 EFI_STATUS Status;
1033 EMMC_PARTITION *Partition;
1034
1035 Partition = EMMC_PARTITION_DATA_FROM_BLKIO (This);
1036
1037 Status = EmmcReadWrite (Partition, MediaId, Lba, Buffer, BufferSize, FALSE, NULL);
1038 return Status;
1039}
1040
1052EFIAPI
1055 )
1056{
1057 //
1058 // return directly
1059 //
1060 return EFI_SUCCESS;
1061}
1062
1075EFIAPI
1078 IN BOOLEAN ExtendedVerification
1079 )
1080{
1081 EMMC_PARTITION *Partition;
1082 LIST_ENTRY *Link;
1083 LIST_ENTRY *NextLink;
1084 EMMC_REQUEST *Request;
1085 EFI_TPL OldTpl;
1086
1087 Partition = EMMC_PARTITION_DATA_FROM_BLKIO2 (This);
1088
1089 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1090 for (Link = GetFirstNode (&Partition->Queue);
1091 !IsNull (&Partition->Queue, Link);
1092 Link = NextLink)
1093 {
1094 NextLink = GetNextNode (&Partition->Queue, Link);
1095 RemoveEntryList (Link);
1096
1097 Request = EMMC_REQUEST_FROM_LINK (Link);
1098
1099 gBS->CloseEvent (Request->Event);
1100 Request->Token->TransactionStatus = EFI_ABORTED;
1101
1102 if (Request->IsEnd) {
1103 gBS->SignalEvent (Request->Token->Event);
1104 }
1105
1106 FreePool (Request);
1107 }
1108
1109 gBS->RestoreTPL (OldTpl);
1110
1111 return EFI_SUCCESS;
1112}
1113
1141EFIAPI
1144 IN UINT32 MediaId,
1145 IN EFI_LBA Lba,
1146 IN OUT EFI_BLOCK_IO2_TOKEN *Token,
1147 IN UINTN BufferSize,
1148 OUT VOID *Buffer
1149 )
1150{
1151 EFI_STATUS Status;
1152 EMMC_PARTITION *Partition;
1153
1154 Partition = EMMC_PARTITION_DATA_FROM_BLKIO2 (This);
1155
1156 Status = EmmcReadWrite (Partition, MediaId, Lba, Buffer, BufferSize, TRUE, Token);
1157 return Status;
1158}
1159
1183EFIAPI
1186 IN UINT32 MediaId,
1187 IN EFI_LBA Lba,
1188 IN OUT EFI_BLOCK_IO2_TOKEN *Token,
1189 IN UINTN BufferSize,
1190 IN VOID *Buffer
1191 )
1192{
1193 EFI_STATUS Status;
1194 EMMC_PARTITION *Partition;
1195
1196 Partition = EMMC_PARTITION_DATA_FROM_BLKIO2 (This);
1197
1198 Status = EmmcReadWrite (Partition, MediaId, Lba, Buffer, BufferSize, FALSE, Token);
1199 return Status;
1200}
1201
1214EFIAPI
1218 )
1219{
1220 //
1221 // Signal event and return directly.
1222 //
1223 if ((Token != NULL) && (Token->Event != NULL)) {
1224 Token->TransactionStatus = EFI_SUCCESS;
1225 gBS->SignalEvent (Token->Event);
1226 }
1227
1228 return EFI_SUCCESS;
1229}
1230
1307EFIAPI
1310 IN UINT32 MediaId,
1311 IN UINT64 Timeout,
1312 IN UINT8 SecurityProtocolId,
1313 IN UINT16 SecurityProtocolSpecificData,
1314 IN UINTN PayloadBufferSize,
1315 OUT VOID *PayloadBuffer,
1316 OUT UINTN *PayloadTransferSize,
1317 IN BOOLEAN IsRead
1318 )
1319{
1320 EFI_STATUS Status;
1321 EMMC_PARTITION *Partition;
1322 EMMC_DEVICE *Device;
1323 EFI_BLOCK_IO_MEDIA *Media;
1324 UINTN BlockSize;
1325 UINTN BlockNum;
1326 UINTN IoAlign;
1327 UINTN Remaining;
1328 UINT32 MaxBlock;
1329 UINT8 PartitionConfig;
1330
1331 Status = EFI_SUCCESS;
1332 Partition = EMMC_PARTITION_DATA_FROM_SSP (This);
1333 Device = Partition->Device;
1334 Media = &Partition->BlockMedia;
1335
1336 if (PayloadTransferSize != NULL) {
1337 *PayloadTransferSize = 0;
1338 }
1339
1340 if ((PayloadBuffer == NULL) && (PayloadBufferSize != 0)) {
1341 return EFI_INVALID_PARAMETER;
1342 }
1343
1344 if (MediaId != Media->MediaId) {
1345 return EFI_MEDIA_CHANGED;
1346 }
1347
1348 if (PayloadBufferSize == 0) {
1349 return EFI_SUCCESS;
1350 }
1351
1352 BlockSize = Media->BlockSize;
1353 if ((PayloadBufferSize % BlockSize) != 0) {
1354 return EFI_BAD_BUFFER_SIZE;
1355 }
1356
1357 BlockNum = PayloadBufferSize / BlockSize;
1358
1359 IoAlign = Media->IoAlign;
1360 if ((IoAlign > 0) && (((UINTN)PayloadBuffer & (IoAlign - 1)) != 0)) {
1361 return EFI_INVALID_PARAMETER;
1362 }
1363
1364 //
1365 // Security protocol interface is synchronous transfer.
1366 // Waiting for async I/O list to be empty before any operation.
1367 //
1368 while (!IsListEmpty (&Partition->Queue)) {
1369 }
1370
1371 //
1372 // Check if needs to switch partition access.
1373 //
1374 PartitionConfig = Device->ExtCsd.PartitionConfig;
1375 if ((PartitionConfig & 0x7) != Partition->PartitionType) {
1376 PartitionConfig &= (UINT8) ~0x7;
1377 PartitionConfig |= Partition->PartitionType;
1378 Status = EmmcSetExtCsd (Partition, OFFSET_OF (EMMC_EXT_CSD, PartitionConfig), PartitionConfig, NULL, FALSE);
1379 if (EFI_ERROR (Status)) {
1380 return Status;
1381 }
1382
1383 Device->ExtCsd.PartitionConfig = PartitionConfig;
1384 }
1385
1386 //
1387 // Start to execute data transfer. The max block number in single cmd is 65535 blocks.
1388 //
1389 Remaining = BlockNum;
1390 MaxBlock = 0xFFFF;
1391
1392 while (Remaining > 0) {
1393 if (Remaining <= MaxBlock) {
1394 BlockNum = Remaining;
1395 } else {
1396 BlockNum = MaxBlock;
1397 }
1398
1399 Status = EmmcSetBlkCount (Partition, (UINT16)BlockNum, NULL, FALSE);
1400 if (EFI_ERROR (Status)) {
1401 return Status;
1402 }
1403
1404 PayloadBufferSize = BlockNum * BlockSize;
1405 Status = EmmcProtocolInOut (Partition, SecurityProtocolId, SecurityProtocolSpecificData, PayloadBufferSize, PayloadBuffer, IsRead, Timeout, NULL, FALSE);
1406 if (EFI_ERROR (Status)) {
1407 return Status;
1408 }
1409
1410 PayloadBuffer = (UINT8 *)PayloadBuffer + PayloadBufferSize;
1411 Remaining -= BlockNum;
1412 if (PayloadTransferSize != NULL) {
1413 *PayloadTransferSize += PayloadBufferSize;
1414 }
1415 }
1416
1417 return Status;
1418}
1419
1495EFIAPI
1498 IN UINT32 MediaId,
1499 IN UINT64 Timeout,
1500 IN UINT8 SecurityProtocolId,
1501 IN UINT16 SecurityProtocolSpecificData,
1502 IN UINTN PayloadBufferSize,
1503 OUT VOID *PayloadBuffer,
1504 OUT UINTN *PayloadTransferSize
1505 )
1506{
1507 EFI_STATUS Status;
1508
1509 if ((PayloadTransferSize == NULL) && (PayloadBufferSize != 0)) {
1510 return EFI_INVALID_PARAMETER;
1511 }
1512
1513 Status = EmmcSecurityProtocolInOut (
1514 This,
1515 MediaId,
1516 Timeout,
1517 SecurityProtocolId,
1518 SecurityProtocolSpecificData,
1519 PayloadBufferSize,
1520 PayloadBuffer,
1521 PayloadTransferSize,
1522 TRUE
1523 );
1524
1525 return Status;
1526}
1527
1592EFIAPI
1595 IN UINT32 MediaId,
1596 IN UINT64 Timeout,
1597 IN UINT8 SecurityProtocolId,
1598 IN UINT16 SecurityProtocolSpecificData,
1599 IN UINTN PayloadBufferSize,
1600 IN VOID *PayloadBuffer
1601 )
1602{
1603 EFI_STATUS Status;
1604
1605 Status = EmmcSecurityProtocolInOut (
1606 This,
1607 MediaId,
1608 Timeout,
1609 SecurityProtocolId,
1610 SecurityProtocolSpecificData,
1611 PayloadBufferSize,
1612 PayloadBuffer,
1613 NULL,
1614 FALSE
1615 );
1616
1617 return Status;
1618}
1619
1636 IN EMMC_PARTITION *Partition,
1637 IN EFI_LBA StartLba,
1638 IN EFI_BLOCK_IO2_TOKEN *Token,
1639 IN BOOLEAN IsEnd
1640 )
1641{
1642 EFI_STATUS Status;
1644 EMMC_DEVICE *Device;
1645 EMMC_REQUEST *EraseBlockStart;
1646 EFI_TPL OldTpl;
1647
1648 EraseBlockStart = NULL;
1649
1650 Device = Partition->Device;
1651 PassThru = Device->Private->PassThru;
1652
1653 EraseBlockStart = AllocateZeroPool (sizeof (EMMC_REQUEST));
1654 if (EraseBlockStart == NULL) {
1655 Status = EFI_OUT_OF_RESOURCES;
1656 goto Error;
1657 }
1658
1659 EraseBlockStart->Signature = EMMC_REQUEST_SIGNATURE;
1660 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1661 InsertTailList (&Partition->Queue, &EraseBlockStart->Link);
1662 gBS->RestoreTPL (OldTpl);
1663 EraseBlockStart->Packet.SdMmcCmdBlk = &EraseBlockStart->SdMmcCmdBlk;
1664 EraseBlockStart->Packet.SdMmcStatusBlk = &EraseBlockStart->SdMmcStatusBlk;
1665 EraseBlockStart->Packet.Timeout = EMMC_GENERIC_TIMEOUT;
1666
1667 EraseBlockStart->SdMmcCmdBlk.CommandIndex = EMMC_ERASE_GROUP_START;
1668 EraseBlockStart->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
1669 EraseBlockStart->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
1670
1671 if (Device->SectorAddressing) {
1672 EraseBlockStart->SdMmcCmdBlk.CommandArgument = (UINT32)StartLba;
1673 } else {
1674 EraseBlockStart->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (StartLba, Partition->BlockMedia.BlockSize);
1675 }
1676
1677 EraseBlockStart->IsEnd = IsEnd;
1678 EraseBlockStart->Token = Token;
1679
1680 if ((Token != NULL) && (Token->Event != NULL)) {
1681 Status = gBS->CreateEvent (
1682 EVT_NOTIFY_SIGNAL,
1683 TPL_NOTIFY,
1685 EraseBlockStart,
1686 &EraseBlockStart->Event
1687 );
1688 if (EFI_ERROR (Status)) {
1689 goto Error;
1690 }
1691 } else {
1692 EraseBlockStart->Event = NULL;
1693 }
1694
1695 Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlockStart->Packet, EraseBlockStart->Event);
1696
1697Error:
1698 if ((Token != NULL) && (Token->Event != NULL)) {
1699 //
1700 // For asynchronous operation, only free request and event in error case.
1701 // The request and event will be freed in asynchronous callback for success case.
1702 //
1703 if (EFI_ERROR (Status) && (EraseBlockStart != NULL)) {
1704 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1705 RemoveEntryList (&EraseBlockStart->Link);
1706 gBS->RestoreTPL (OldTpl);
1707 if (EraseBlockStart->Event != NULL) {
1708 gBS->CloseEvent (EraseBlockStart->Event);
1709 }
1710
1711 FreePool (EraseBlockStart);
1712 }
1713 } else {
1714 //
1715 // For synchronous operation, free request whatever the execution result is.
1716 //
1717 if (EraseBlockStart != NULL) {
1718 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1719 RemoveEntryList (&EraseBlockStart->Link);
1720 gBS->RestoreTPL (OldTpl);
1721 FreePool (EraseBlockStart);
1722 }
1723 }
1724
1725 return Status;
1726}
1727
1744 IN EMMC_PARTITION *Partition,
1745 IN EFI_LBA EndLba,
1746 IN EFI_BLOCK_IO2_TOKEN *Token,
1747 IN BOOLEAN IsEnd
1748 )
1749{
1750 EFI_STATUS Status;
1752 EMMC_DEVICE *Device;
1753 EMMC_REQUEST *EraseBlockEnd;
1754 EFI_TPL OldTpl;
1755
1756 EraseBlockEnd = NULL;
1757
1758 Device = Partition->Device;
1759 PassThru = Device->Private->PassThru;
1760
1761 EraseBlockEnd = AllocateZeroPool (sizeof (EMMC_REQUEST));
1762 if (EraseBlockEnd == NULL) {
1763 Status = EFI_OUT_OF_RESOURCES;
1764 goto Error;
1765 }
1766
1767 EraseBlockEnd->Signature = EMMC_REQUEST_SIGNATURE;
1768 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1769 InsertTailList (&Partition->Queue, &EraseBlockEnd->Link);
1770 gBS->RestoreTPL (OldTpl);
1771 EraseBlockEnd->Packet.SdMmcCmdBlk = &EraseBlockEnd->SdMmcCmdBlk;
1772 EraseBlockEnd->Packet.SdMmcStatusBlk = &EraseBlockEnd->SdMmcStatusBlk;
1773 EraseBlockEnd->Packet.Timeout = EMMC_GENERIC_TIMEOUT;
1774
1775 EraseBlockEnd->SdMmcCmdBlk.CommandIndex = EMMC_ERASE_GROUP_END;
1776 EraseBlockEnd->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
1777 EraseBlockEnd->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
1778
1779 if (Device->SectorAddressing) {
1780 EraseBlockEnd->SdMmcCmdBlk.CommandArgument = (UINT32)EndLba;
1781 } else {
1782 EraseBlockEnd->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (EndLba, Partition->BlockMedia.BlockSize);
1783 }
1784
1785 EraseBlockEnd->IsEnd = IsEnd;
1786 EraseBlockEnd->Token = Token;
1787
1788 if ((Token != NULL) && (Token->Event != NULL)) {
1789 Status = gBS->CreateEvent (
1790 EVT_NOTIFY_SIGNAL,
1791 TPL_NOTIFY,
1793 EraseBlockEnd,
1794 &EraseBlockEnd->Event
1795 );
1796 if (EFI_ERROR (Status)) {
1797 goto Error;
1798 }
1799 } else {
1800 EraseBlockEnd->Event = NULL;
1801 }
1802
1803 Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlockEnd->Packet, EraseBlockEnd->Event);
1804
1805Error:
1806 if ((Token != NULL) && (Token->Event != NULL)) {
1807 //
1808 // For asynchronous operation, only free request and event in error case.
1809 // The request and event will be freed in asynchronous callback for success case.
1810 //
1811 if (EFI_ERROR (Status) && (EraseBlockEnd != NULL)) {
1812 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1813 RemoveEntryList (&EraseBlockEnd->Link);
1814 gBS->RestoreTPL (OldTpl);
1815 if (EraseBlockEnd->Event != NULL) {
1816 gBS->CloseEvent (EraseBlockEnd->Event);
1817 }
1818
1819 FreePool (EraseBlockEnd);
1820 }
1821 } else {
1822 //
1823 // For synchronous operation, free request whatever the execution result is.
1824 //
1825 if (EraseBlockEnd != NULL) {
1826 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1827 RemoveEntryList (&EraseBlockEnd->Link);
1828 gBS->RestoreTPL (OldTpl);
1829 FreePool (EraseBlockEnd);
1830 }
1831 }
1832
1833 return Status;
1834}
1835
1851 IN EMMC_PARTITION *Partition,
1852 IN EFI_BLOCK_IO2_TOKEN *Token,
1853 IN BOOLEAN IsEnd
1854 )
1855{
1856 EFI_STATUS Status;
1858 EMMC_DEVICE *Device;
1859 EMMC_REQUEST *EraseBlock;
1860 EFI_TPL OldTpl;
1861
1862 EraseBlock = NULL;
1863
1864 Device = Partition->Device;
1865 PassThru = Device->Private->PassThru;
1866
1867 EraseBlock = AllocateZeroPool (sizeof (EMMC_REQUEST));
1868 if (EraseBlock == NULL) {
1869 Status = EFI_OUT_OF_RESOURCES;
1870 goto Error;
1871 }
1872
1873 EraseBlock->Signature = EMMC_REQUEST_SIGNATURE;
1874 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1875 InsertTailList (&Partition->Queue, &EraseBlock->Link);
1876 gBS->RestoreTPL (OldTpl);
1877 EraseBlock->Packet.SdMmcCmdBlk = &EraseBlock->SdMmcCmdBlk;
1878 EraseBlock->Packet.SdMmcStatusBlk = &EraseBlock->SdMmcStatusBlk;
1879 EraseBlock->Packet.Timeout = EMMC_GENERIC_TIMEOUT;
1880
1881 EraseBlock->SdMmcCmdBlk.CommandIndex = EMMC_ERASE;
1882 EraseBlock->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
1883 EraseBlock->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b;
1884 if ((Device->ExtCsd.SecFeatureSupport & BIT4) != 0) {
1885 //
1886 // Perform a Trim operation which applies the erase operation to write blocks
1887 // instead of erase groups. (Spec JESD84-B51, eMMC Electrical Standard 5.1,
1888 // Section 6.6.10 and 6.10.4)
1889 //
1890 EraseBlock->SdMmcCmdBlk.CommandArgument = 1;
1891 }
1892
1893 EraseBlock->IsEnd = IsEnd;
1894 EraseBlock->Token = Token;
1895
1896 if ((Token != NULL) && (Token->Event != NULL)) {
1897 Status = gBS->CreateEvent (
1898 EVT_NOTIFY_SIGNAL,
1899 TPL_NOTIFY,
1901 EraseBlock,
1902 &EraseBlock->Event
1903 );
1904 if (EFI_ERROR (Status)) {
1905 goto Error;
1906 }
1907 } else {
1908 EraseBlock->Event = NULL;
1909 }
1910
1911 Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlock->Packet, EraseBlock->Event);
1912
1913Error:
1914 if ((Token != NULL) && (Token->Event != NULL)) {
1915 //
1916 // For asynchronous operation, only free request and event in error case.
1917 // The request and event will be freed in asynchronous callback for success case.
1918 //
1919 if (EFI_ERROR (Status) && (EraseBlock != NULL)) {
1920 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1921 RemoveEntryList (&EraseBlock->Link);
1922 gBS->RestoreTPL (OldTpl);
1923 if (EraseBlock->Event != NULL) {
1924 gBS->CloseEvent (EraseBlock->Event);
1925 }
1926
1927 FreePool (EraseBlock);
1928 }
1929 } else {
1930 //
1931 // For synchronous operation, free request whatever the execution result is.
1932 //
1933 if (EraseBlock != NULL) {
1934 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1935 RemoveEntryList (&EraseBlock->Link);
1936 gBS->RestoreTPL (OldTpl);
1937 FreePool (EraseBlock);
1938 }
1939 }
1940
1941 return Status;
1942}
1943
1959 IN EMMC_PARTITION *Partition,
1960 IN EFI_LBA StartLba,
1961 IN UINTN Size
1962 )
1963{
1964 EFI_STATUS Status;
1965 UINT8 *Buffer;
1966 UINT32 MediaId;
1967
1968 Buffer = AllocateZeroPool (Size);
1969 if (Buffer == NULL) {
1970 return EFI_OUT_OF_RESOURCES;
1971 }
1972
1973 MediaId = Partition->BlockMedia.MediaId;
1974
1975 Status = EmmcReadWrite (Partition, MediaId, StartLba, Buffer, Size, FALSE, NULL);
1976 FreePool (Buffer);
1977
1978 return Status;
1979}
1980
2009EFIAPI
2012 IN UINT32 MediaId,
2013 IN EFI_LBA Lba,
2015 IN UINTN Size
2016 )
2017{
2018 EFI_STATUS Status;
2019 EFI_BLOCK_IO_MEDIA *Media;
2020 UINTN BlockSize;
2021 UINTN BlockNum;
2022 EFI_LBA FirstLba;
2023 EFI_LBA LastLba;
2024 EFI_LBA StartGroupLba;
2025 EFI_LBA EndGroupLba;
2026 UINT32 EraseGroupSize;
2027 UINT32 Remainder;
2028 UINTN WriteZeroSize;
2029 UINT8 PartitionConfig;
2030 EMMC_PARTITION *Partition;
2031 EMMC_DEVICE *Device;
2032
2033 Status = EFI_SUCCESS;
2034 Partition = EMMC_PARTITION_DATA_FROM_ERASEBLK (This);
2035 Device = Partition->Device;
2036 Media = &Partition->BlockMedia;
2037
2038 if (MediaId != Media->MediaId) {
2039 return EFI_MEDIA_CHANGED;
2040 }
2041
2042 if (Media->ReadOnly) {
2043 return EFI_WRITE_PROTECTED;
2044 }
2045
2046 //
2047 // Check parameters.
2048 //
2049 BlockSize = Media->BlockSize;
2050 if ((Size % BlockSize) != 0) {
2051 return EFI_INVALID_PARAMETER;
2052 }
2053
2054 BlockNum = Size / BlockSize;
2055 if ((Lba + BlockNum - 1) > Media->LastBlock) {
2056 return EFI_INVALID_PARAMETER;
2057 }
2058
2059 if ((Token != NULL) && (Token->Event != NULL)) {
2060 Token->TransactionStatus = EFI_SUCCESS;
2061 }
2062
2063 FirstLba = Lba;
2064 LastLba = Lba + BlockNum - 1;
2065
2066 //
2067 // Check if needs to switch partition access.
2068 //
2069 PartitionConfig = Device->ExtCsd.PartitionConfig;
2070 if ((PartitionConfig & 0x7) != Partition->PartitionType) {
2071 PartitionConfig &= (UINT8) ~0x7;
2072 PartitionConfig |= Partition->PartitionType;
2073 Status = EmmcSetExtCsd (Partition, OFFSET_OF (EMMC_EXT_CSD, PartitionConfig), PartitionConfig, (EFI_BLOCK_IO2_TOKEN *)Token, FALSE);
2074 if (EFI_ERROR (Status)) {
2075 return Status;
2076 }
2077
2078 Device->ExtCsd.PartitionConfig = PartitionConfig;
2079 }
2080
2081 if ((Device->ExtCsd.SecFeatureSupport & BIT4) == 0) {
2082 //
2083 // If the Trim operation is not supported by the device, handle the erase
2084 // of blocks that do not form a complete erase group separately.
2085 //
2086 EraseGroupSize = This->EraseLengthGranularity;
2087
2088 DivU64x32Remainder (FirstLba, EraseGroupSize, &Remainder);
2089 StartGroupLba = (Remainder == 0) ? FirstLba : (FirstLba + EraseGroupSize - Remainder);
2090
2091 DivU64x32Remainder (LastLba + 1, EraseGroupSize, &Remainder);
2092 EndGroupLba = LastLba + 1 - Remainder;
2093
2094 //
2095 // If the size to erase is smaller than the erase group size, the whole
2096 // erase operation is performed by writing zeros.
2097 //
2098 if (BlockNum < EraseGroupSize) {
2099 Status = EmmcWriteZeros (Partition, FirstLba, Size);
2100 if (EFI_ERROR (Status)) {
2101 return Status;
2102 }
2103
2104 DEBUG ((
2105 DEBUG_INFO,
2106 "EmmcEraseBlocks(): Lba 0x%x BlkNo 0x%x Event %p with %r\n",
2107 Lba,
2108 BlockNum,
2109 (Token != NULL) ? Token->Event : NULL,
2110 Status
2111 ));
2112
2113 if ((Token != NULL) && (Token->Event != NULL)) {
2114 Token->TransactionStatus = EFI_SUCCESS;
2115 gBS->SignalEvent (Token->Event);
2116 }
2117
2118 return EFI_SUCCESS;
2119 }
2120
2121 //
2122 // If the starting LBA to erase is not aligned with the start of an erase
2123 // group, write zeros to erase the data from starting LBA to the end of the
2124 // current erase group.
2125 //
2126 if (StartGroupLba > FirstLba) {
2127 WriteZeroSize = (UINTN)(StartGroupLba - FirstLba) * BlockSize;
2128 Status = EmmcWriteZeros (Partition, FirstLba, WriteZeroSize);
2129 if (EFI_ERROR (Status)) {
2130 return Status;
2131 }
2132 }
2133
2134 //
2135 // If the ending LBA to erase is not aligned with the end of an erase
2136 // group, write zeros to erase the data from the start of the erase group
2137 // to the ending LBA.
2138 //
2139 if (EndGroupLba <= LastLba) {
2140 WriteZeroSize = (UINTN)(LastLba + 1 - EndGroupLba) * BlockSize;
2141 Status = EmmcWriteZeros (Partition, EndGroupLba, WriteZeroSize);
2142 if (EFI_ERROR (Status)) {
2143 return Status;
2144 }
2145 }
2146
2147 //
2148 // Check whether there is erase group to erase.
2149 //
2150 if (EndGroupLba <= StartGroupLba) {
2151 DEBUG ((
2152 DEBUG_INFO,
2153 "EmmcEraseBlocks(): Lba 0x%x BlkNo 0x%x Event %p with %r\n",
2154 Lba,
2155 BlockNum,
2156 (Token != NULL) ? Token->Event : NULL,
2157 Status
2158 ));
2159
2160 if ((Token != NULL) && (Token->Event != NULL)) {
2161 Token->TransactionStatus = EFI_SUCCESS;
2162 gBS->SignalEvent (Token->Event);
2163 }
2164
2165 return EFI_SUCCESS;
2166 }
2167
2168 FirstLba = StartGroupLba;
2169 LastLba = EndGroupLba - 1;
2170 }
2171
2172 Status = EmmcEraseBlockStart (Partition, FirstLba, (EFI_BLOCK_IO2_TOKEN *)Token, FALSE);
2173 if (EFI_ERROR (Status)) {
2174 return Status;
2175 }
2176
2177 Status = EmmcEraseBlockEnd (Partition, LastLba, (EFI_BLOCK_IO2_TOKEN *)Token, FALSE);
2178 if (EFI_ERROR (Status)) {
2179 return Status;
2180 }
2181
2182 Status = EmmcEraseBlock (Partition, (EFI_BLOCK_IO2_TOKEN *)Token, TRUE);
2183 if (EFI_ERROR (Status)) {
2184 return Status;
2185 }
2186
2187 DEBUG ((
2188 DEBUG_INFO,
2189 "EmmcEraseBlocks(): Lba 0x%x BlkNo 0x%x Event %p with %r\n",
2190 Lba,
2191 BlockNum,
2192 (Token != NULL) ? Token->Event : NULL,
2193 Status
2194 ));
2195
2196 return Status;
2197}
UINT64 UINTN
BOOLEAN EFIAPI IsNull(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:443
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:333
UINT64 EFIAPI DivU64x32(IN UINT64 Dividend, IN UINT32 Divisor)
Definition: DivU64x32.c:29
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
Definition: MultU64x32.c:27
UINT64 EFIAPI DivU64x32Remainder(IN UINT64 Dividend, IN UINT32 Divisor, OUT UINT32 *Remainder OPTIONAL)
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
EFI_STATUS EmmcSetBlkCount(IN EMMC_PARTITION *Partition, IN UINT16 BlockNum, IN EFI_BLOCK_IO2_TOKEN *Token, IN BOOLEAN IsEnd)
Definition: EmmcBlockIo.c:422
EFI_STATUS EFIAPI EmmcSecurityProtocolIn(IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This, IN UINT32 MediaId, IN UINT64 Timeout, IN UINT8 SecurityProtocolId, IN UINT16 SecurityProtocolSpecificData, IN UINTN PayloadBufferSize, OUT VOID *PayloadBuffer, OUT UINTN *PayloadTransferSize)
Definition: EmmcBlockIo.c:1496
EFI_STATUS EFIAPI EmmcWriteBlocks(IN EFI_BLOCK_IO_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN UINTN BufferSize, IN VOID *Buffer)
Definition: EmmcBlockIo.c:1024
EFI_STATUS EmmcSetExtCsd(IN EMMC_PARTITION *Partition, IN UINT8 Offset, IN UINT8 Value, IN EFI_BLOCK_IO2_TOKEN *Token, IN BOOLEAN IsEnd)
Definition: EmmcBlockIo.c:313
EFI_STATUS EFIAPI EmmcResetEx(IN EFI_BLOCK_IO2_PROTOCOL *This, IN BOOLEAN ExtendedVerification)
Definition: EmmcBlockIo.c:1076
EFI_STATUS EmmcEraseBlockEnd(IN EMMC_PARTITION *Partition, IN EFI_LBA EndLba, IN EFI_BLOCK_IO2_TOKEN *Token, IN BOOLEAN IsEnd)
Definition: EmmcBlockIo.c:1743
EFI_STATUS EFIAPI EmmcReadBlocksEx(IN EFI_BLOCK_IO2_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN OUT EFI_BLOCK_IO2_TOKEN *Token, IN UINTN BufferSize, OUT VOID *Buffer)
Definition: EmmcBlockIo.c:1142
EFI_STATUS EmmcSendStatus(IN EMMC_DEVICE *Device, IN UINT16 Rca, OUT UINT32 *DevStatus)
Definition: EmmcBlockIo.c:114
EFI_STATUS EFIAPI EmmcReadBlocks(IN EFI_BLOCK_IO_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN UINTN BufferSize, OUT VOID *Buffer)
Definition: EmmcBlockIo.c:985
EFI_STATUS EmmcWriteZeros(IN EMMC_PARTITION *Partition, IN EFI_LBA StartLba, IN UINTN Size)
Definition: EmmcBlockIo.c:1958
EFI_STATUS EFIAPI EmmcSecurityProtocolInOut(IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This, IN UINT32 MediaId, IN UINT64 Timeout, IN UINT8 SecurityProtocolId, IN UINT16 SecurityProtocolSpecificData, IN UINTN PayloadBufferSize, OUT VOID *PayloadBuffer, OUT UINTN *PayloadTransferSize, IN BOOLEAN IsRead)
Definition: EmmcBlockIo.c:1308
EFI_STATUS EmmcEraseBlockStart(IN EMMC_PARTITION *Partition, IN EFI_LBA StartLba, IN EFI_BLOCK_IO2_TOKEN *Token, IN BOOLEAN IsEnd)
Definition: EmmcBlockIo.c:1635
EFI_STATUS EFIAPI EmmcWriteBlocksEx(IN EFI_BLOCK_IO2_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN OUT EFI_BLOCK_IO2_TOKEN *Token, IN UINTN BufferSize, IN VOID *Buffer)
Definition: EmmcBlockIo.c:1184
EFI_STATUS EmmcGetCsd(IN EMMC_DEVICE *Device, IN UINT16 Rca, OUT EMMC_CSD *Csd)
Definition: EmmcBlockIo.c:161
EFI_STATUS EmmcRwMultiBlocks(IN EMMC_PARTITION *Partition, IN EFI_LBA Lba, IN VOID *Buffer, IN UINTN BufferSize, IN BOOLEAN IsRead, IN EFI_BLOCK_IO2_TOKEN *Token, IN BOOLEAN IsEnd)
Definition: EmmcBlockIo.c:664
EFI_STATUS EmmcGetExtCsd(IN EMMC_DEVICE *Device, OUT EMMC_EXT_CSD *ExtCsd)
Definition: EmmcBlockIo.c:264
EFI_STATUS EFIAPI EmmcEraseBlocks(IN EFI_ERASE_BLOCK_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN OUT EFI_ERASE_BLOCK_TOKEN *Token, IN UINTN Size)
Definition: EmmcBlockIo.c:2010
EFI_STATUS EFIAPI EmmcFlushBlocksEx(IN EFI_BLOCK_IO2_PROTOCOL *This, IN OUT EFI_BLOCK_IO2_TOKEN *Token)
Definition: EmmcBlockIo.c:1215
EFI_STATUS EFIAPI EmmcSecurityProtocolOut(IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This, IN UINT32 MediaId, IN UINT64 Timeout, IN UINT8 SecurityProtocolId, IN UINT16 SecurityProtocolSpecificData, IN UINTN PayloadBufferSize, IN VOID *PayloadBuffer)
Definition: EmmcBlockIo.c:1593
EFI_STATUS EmmcProtocolInOut(IN EMMC_PARTITION *Partition, IN UINT8 SecurityProtocol, IN UINT16 SecurityProtocolSpecificData, IN UINTN PayloadBufferSize, OUT VOID *PayloadBuffer, IN BOOLEAN IsRead, IN UINT64 Timeout, IN EFI_BLOCK_IO2_TOKEN *Token, IN BOOLEAN IsEnd)
Definition: EmmcBlockIo.c:535
EFI_STATUS EmmcGetCid(IN EMMC_DEVICE *Device, IN UINT16 Rca, OUT EMMC_CID *Cid)
Definition: EmmcBlockIo.c:213
EFI_STATUS EmmcSelect(IN EMMC_DEVICE *Device, IN UINT16 Rca)
Definition: EmmcBlockIo.c:71
EFI_STATUS EmmcEraseBlock(IN EMMC_PARTITION *Partition, IN EFI_BLOCK_IO2_TOKEN *Token, IN BOOLEAN IsEnd)
Definition: EmmcBlockIo.c:1850
EFI_STATUS EFIAPI EmmcFlushBlocks(IN EFI_BLOCK_IO_PROTOCOL *This)
Definition: EmmcBlockIo.c:1053
VOID EFIAPI AsyncIoCallback(IN EFI_EVENT Event, IN VOID *Context)
Definition: EmmcBlockIo.c:21
EFI_STATUS EmmcReadWrite(IN EMMC_PARTITION *Partition, IN UINT32 MediaId, IN EFI_LBA Lba, IN OUT VOID *Buffer, IN UINTN BufferSize, IN BOOLEAN IsRead, IN OUT EFI_BLOCK_IO2_TOKEN *Token)
Definition: EmmcBlockIo.c:803
EFI_STATUS EFIAPI EmmcReset(IN EFI_BLOCK_IO_PROTOCOL *This, IN BOOLEAN ExtendedVerification)
Definition: EmmcBlockIo.c:944
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OFFSET_OF(TYPE, Field)
Definition: Base.h:758
#define OUT
Definition: Base.h:284
#define DEBUG_CODE_BEGIN()
Definition: DebugLib.h:564
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define DEBUG_CODE_END()
Definition: DebugLib.h:578
UINT64 EFI_LBA
Definition: UefiBaseType.h:45
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
UINTN EFI_TPL
Definition: UefiBaseType.h:41
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_EVENT Event
Definition: BlockIo2.h:34
EFI_STATUS TransactionStatus
Definition: BlockIo2.h:39
UINT32 BlockSize
Definition: BlockIo.h:167
EFI_LBA LastBlock
Definition: BlockIo.h:178
BOOLEAN ReadOnly
Definition: BlockIo.h:156
Definition: Emmc.h:71
Definition: Emmc.h:84