]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c
MdeModulePkg/Bus/Sd: Fix various typos
[mirror_edk2.git] / MdeModulePkg / Bus / Sd / SdDxe / SdBlockIo.c
index b7a5fe49ae1c2dc89a4c2a9dbd954afd9a16d0e3..9f42abe7e2ad32a7a4bf0874c823a8884c4d6fe2 100644 (file)
@@ -1,21 +1,15 @@
 /** @file\r
   The helper functions for BlockIo and BlockIo2 protocol.\r
 \r
-  Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
-  This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "SdDxe.h"\r
 \r
 /**\r
-  Nonblocking I/O callback funtion when the event is signaled.\r
+  Nonblocking I/O callback function when the event is signaled.\r
 \r
   @param[in]  Event     The Event this notify function registered to.\r
   @param[in]  Context   Pointer to the context data registered to the\r
@@ -340,7 +334,7 @@ SdRwSingleBlock (
   }\r
 \r
   RwSingleBlkReq->Signature = SD_REQUEST_SIGNATURE;\r
-  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
   InsertTailList (&Device->Queue, &RwSingleBlkReq->Link);\r
   gBS->RestoreTPL (OldTpl);\r
   RwSingleBlkReq->Packet.SdMmcCmdBlk    = &RwSingleBlkReq->SdMmcCmdBlk;\r
@@ -382,7 +376,7 @@ SdRwSingleBlock (
   if ((Token != NULL) && (Token->Event != NULL)) {\r
     Status = gBS->CreateEvent (\r
                     EVT_NOTIFY_SIGNAL,\r
-                    TPL_CALLBACK,\r
+                    TPL_NOTIFY,\r
                     AsyncIoCallback,\r
                     RwSingleBlkReq,\r
                     &RwSingleBlkReq->Event\r
@@ -403,7 +397,9 @@ Error:
     // The request and event will be freed in asynchronous callback for success case.\r
     //\r
     if (EFI_ERROR (Status) && (RwSingleBlkReq != NULL)) {\r
+      OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
       RemoveEntryList (&RwSingleBlkReq->Link);\r
+      gBS->RestoreTPL (OldTpl);\r
       if (RwSingleBlkReq->Event != NULL) {\r
         gBS->CloseEvent (RwSingleBlkReq->Event);\r
       }\r
@@ -414,7 +410,9 @@ Error:
     // For synchronous operation, free request whatever the execution result is.\r
     //\r
     if (RwSingleBlkReq != NULL) {\r
+      OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
       RemoveEntryList (&RwSingleBlkReq->Link);\r
+      gBS->RestoreTPL (OldTpl);\r
       FreePool (RwSingleBlkReq);\r
     }\r
   }\r
@@ -468,7 +466,7 @@ SdRwMultiBlocks (
   }\r
 \r
   RwMultiBlkReq->Signature = SD_REQUEST_SIGNATURE;\r
-  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
   InsertTailList (&Device->Queue, &RwMultiBlkReq->Link);\r
   gBS->RestoreTPL (OldTpl);\r
   RwMultiBlkReq->Packet.SdMmcCmdBlk    = &RwMultiBlkReq->SdMmcCmdBlk;\r
@@ -510,7 +508,7 @@ SdRwMultiBlocks (
   if ((Token != NULL) && (Token->Event != NULL)) {\r
     Status = gBS->CreateEvent (\r
                     EVT_NOTIFY_SIGNAL,\r
-                    TPL_CALLBACK,\r
+                    TPL_NOTIFY,\r
                     AsyncIoCallback,\r
                     RwMultiBlkReq,\r
                     &RwMultiBlkReq->Event\r
@@ -531,7 +529,9 @@ Error:
     // The request and event will be freed in asynchronous callback for success case.\r
     //\r
     if (EFI_ERROR (Status) && (RwMultiBlkReq != NULL)) {\r
+      OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
       RemoveEntryList (&RwMultiBlkReq->Link);\r
+      gBS->RestoreTPL (OldTpl);\r
       if (RwMultiBlkReq->Event != NULL) {\r
         gBS->CloseEvent (RwMultiBlkReq->Event);\r
       }\r
@@ -542,7 +542,9 @@ Error:
     // For synchronous operation, free request whatever the execution result is.\r
     //\r
     if (RwMultiBlkReq != NULL) {\r
+      OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
       RemoveEntryList (&RwMultiBlkReq->Link);\r
+      gBS->RestoreTPL (OldTpl);\r
       FreePool (RwMultiBlkReq);\r
     }\r
   }\r
@@ -567,7 +569,7 @@ Error:
   @retval EFI_WRITE_PROTECTED   The device can not be read/written to.\r
   @retval EFI_DEVICE_ERROR      The device reported an error while performing the read/write.\r
   @retval EFI_NO_MEDIA          There is no media in the device.\r
-  @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.\r
+  @retval EFI_MEDIA_CHANGED     The MediaId does not match the current device.\r
   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.\r
   @retval EFI_INVALID_PARAMETER The read/write request contains LBAs that are not valid,\r
                                 or the buffer is not on proper alignment.\r
@@ -662,8 +664,9 @@ SdReadWrite (
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
-    DEBUG ((EFI_D_INFO, "Sd%a(): Lba 0x%x BlkNo 0x%x Event %p with %r\n", IsRead ? "Read" : "Write", Lba, BlockNum, Token->Event, Status));\r
-\r
+    DEBUG ((DEBUG_BLKIO, "Sd%a(): Lba 0x%x BlkNo 0x%x Event %p with %r\n",\r
+      IsRead ? "Read" : "Write", Lba, BlockNum,\r
+      (Token != NULL) ? Token->Event : NULL, Status));\r
     Lba   += BlockNum;\r
     Buffer = (UINT8*)Buffer + BufferSize;\r
     Remaining -= BlockNum;\r
@@ -718,7 +721,7 @@ SdReset (
   @retval EFI_SUCCESS           The data was read correctly from the device.\r
   @retval EFI_DEVICE_ERROR      The device reported an error while performing the read.\r
   @retval EFI_NO_MEDIA          There is no media in the device.\r
-  @retval EFI_MEDIA_CHANGED     The MediaId does not matched the current device.\r
+  @retval EFI_MEDIA_CHANGED     The MediaId does not match the current device.\r
   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.\r
   @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,\r
                                 or the buffer is not on proper alignment.\r
@@ -757,7 +760,7 @@ SdReadBlocks (
   @retval EFI_WRITE_PROTECTED   The device can not be written to.\r
   @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.\r
   @retval EFI_NO_MEDIA          There is no media in the device.\r
-  @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.\r
+  @retval EFI_MEDIA_CHANGED     The MediaId does not match the current device.\r
   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.\r
   @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,\r
                                 or the buffer is not on proper alignment.\r
@@ -830,7 +833,7 @@ SdResetEx (
 \r
   Device = SD_DEVICE_DATA_FROM_BLKIO2 (This);\r
 \r
-  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
   for (Link = GetFirstNode (&Device->Queue);\r
        !IsNull (&Device->Queue, Link);\r
        Link = NextLink) {\r
@@ -915,7 +918,7 @@ SdReadBlocksEx (
   @retval EFI_WRITE_PROTECTED   The device can not be written to.\r
   @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.\r
   @retval EFI_NO_MEDIA          There is no media in the device.\r
-  @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.\r
+  @retval EFI_MEDIA_CHANGED     The MediaId does not match the current device.\r
   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.\r
   @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,\r
                                 or the buffer is not on proper alignment.\r
@@ -970,4 +973,402 @@ SdFlushBlocksEx (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Set the erase start address through sync or async I/O request.\r
+\r
+  @param[in]  Device            A pointer to the SD_DEVICE instance.\r
+  @param[in]  StartLba          The starting logical block address to be erased.\r
+  @param[in]  Token             A pointer to the token associated with the transaction.\r
+  @param[in]  IsEnd             A boolean to show whether it's the last cmd in a series of cmds.\r
+                                This parameter is only meaningful in async I/O request.\r
+\r
+  @retval EFI_SUCCESS           The request is executed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be executed due to a lack of resources.\r
+  @retval Others                The request could not be executed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SdEraseBlockStart (\r
+  IN  SD_DEVICE                 *Device,\r
+  IN  EFI_LBA                   StartLba,\r
+  IN  EFI_BLOCK_IO2_TOKEN       *Token,\r
+  IN  BOOLEAN                   IsEnd\r
+  )\r
+{\r
+  EFI_STATUS                           Status;\r
+  EFI_SD_MMC_PASS_THRU_PROTOCOL        *PassThru;\r
+  SD_REQUEST                           *EraseBlockStart;\r
+  EFI_TPL                              OldTpl;\r
+\r
+  EraseBlockStart = NULL;\r
+  PassThru        = Device->Private->PassThru;\r
+\r
+  EraseBlockStart = AllocateZeroPool (sizeof (SD_REQUEST));\r
+  if (EraseBlockStart == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+\r
+  EraseBlockStart->Signature = SD_REQUEST_SIGNATURE;\r
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+  InsertTailList (&Device->Queue, &EraseBlockStart->Link);\r
+  gBS->RestoreTPL (OldTpl);\r
+  EraseBlockStart->Packet.SdMmcCmdBlk    = &EraseBlockStart->SdMmcCmdBlk;\r
+  EraseBlockStart->Packet.SdMmcStatusBlk = &EraseBlockStart->SdMmcStatusBlk;\r
+  EraseBlockStart->Packet.Timeout        = SD_GENERIC_TIMEOUT;\r
+\r
+  EraseBlockStart->SdMmcCmdBlk.CommandIndex = SD_ERASE_WR_BLK_START;\r
+  EraseBlockStart->SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;\r
+  EraseBlockStart->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
+\r
+  if (Device->SectorAddressing) {\r
+    EraseBlockStart->SdMmcCmdBlk.CommandArgument = (UINT32)StartLba;\r
+  } else {\r
+    EraseBlockStart->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (StartLba, Device->BlockMedia.BlockSize);\r
+  }\r
+\r
+  EraseBlockStart->IsEnd = IsEnd;\r
+  EraseBlockStart->Token = Token;\r
+\r
+  if ((Token != NULL) && (Token->Event != NULL)) {\r
+    Status = gBS->CreateEvent (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_NOTIFY,\r
+                    AsyncIoCallback,\r
+                    EraseBlockStart,\r
+                    &EraseBlockStart->Event\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
+    }\r
+  } else {\r
+    EraseBlockStart->Event = NULL;\r
+  }\r
+\r
+  Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlockStart->Packet, EraseBlockStart->Event);\r
+\r
+Error:\r
+  if ((Token != NULL) && (Token->Event != NULL)) {\r
+    //\r
+    // For asynchronous operation, only free request and event in error case.\r
+    // The request and event will be freed in asynchronous callback for success case.\r
+    //\r
+    if (EFI_ERROR (Status) && (EraseBlockStart != NULL)) {\r
+      OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+      RemoveEntryList (&EraseBlockStart->Link);\r
+      gBS->RestoreTPL (OldTpl);\r
+      if (EraseBlockStart->Event != NULL) {\r
+        gBS->CloseEvent (EraseBlockStart->Event);\r
+      }\r
+      FreePool (EraseBlockStart);\r
+    }\r
+  } else {\r
+    //\r
+    // For synchronous operation, free request whatever the execution result is.\r
+    //\r
+    if (EraseBlockStart != NULL) {\r
+      OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+      RemoveEntryList (&EraseBlockStart->Link);\r
+      gBS->RestoreTPL (OldTpl);\r
+      FreePool (EraseBlockStart);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Set the erase end address through sync or async I/O request.\r
+\r
+  @param[in]  Device            A pointer to the SD_DEVICE instance.\r
+  @param[in]  EndLba            The ending logical block address to be erased.\r
+  @param[in]  Token             A pointer to the token associated with the transaction.\r
+  @param[in]  IsEnd             A boolean to show whether it's the last cmd in a series of cmds.\r
+                                This parameter is only meaningful in async I/O request.\r
+\r
+  @retval EFI_SUCCESS           The request is executed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be executed due to a lack of resources.\r
+  @retval Others                The request could not be executed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SdEraseBlockEnd (\r
+  IN  SD_DEVICE                 *Device,\r
+  IN  EFI_LBA                   EndLba,\r
+  IN  EFI_BLOCK_IO2_TOKEN       *Token,\r
+  IN  BOOLEAN                   IsEnd\r
+  )\r
+{\r
+  EFI_STATUS                           Status;\r
+  EFI_SD_MMC_PASS_THRU_PROTOCOL        *PassThru;\r
+  SD_REQUEST                           *EraseBlockEnd;\r
+  EFI_TPL                              OldTpl;\r
+\r
+  EraseBlockEnd = NULL;\r
+  PassThru      = Device->Private->PassThru;\r
+\r
+  EraseBlockEnd = AllocateZeroPool (sizeof (SD_REQUEST));\r
+  if (EraseBlockEnd == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+\r
+  EraseBlockEnd->Signature = SD_REQUEST_SIGNATURE;\r
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+  InsertTailList (&Device->Queue, &EraseBlockEnd->Link);\r
+  gBS->RestoreTPL (OldTpl);\r
+  EraseBlockEnd->Packet.SdMmcCmdBlk    = &EraseBlockEnd->SdMmcCmdBlk;\r
+  EraseBlockEnd->Packet.SdMmcStatusBlk = &EraseBlockEnd->SdMmcStatusBlk;\r
+  EraseBlockEnd->Packet.Timeout        = SD_GENERIC_TIMEOUT;\r
+\r
+  EraseBlockEnd->SdMmcCmdBlk.CommandIndex = SD_ERASE_WR_BLK_END;\r
+  EraseBlockEnd->SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;\r
+  EraseBlockEnd->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
+\r
+  if (Device->SectorAddressing) {\r
+    EraseBlockEnd->SdMmcCmdBlk.CommandArgument = (UINT32)EndLba;\r
+  } else {\r
+    EraseBlockEnd->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (EndLba, Device->BlockMedia.BlockSize);\r
+  }\r
+\r
+  EraseBlockEnd->IsEnd = IsEnd;\r
+  EraseBlockEnd->Token = Token;\r
+\r
+  if ((Token != NULL) && (Token->Event != NULL)) {\r
+    Status = gBS->CreateEvent (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_NOTIFY,\r
+                    AsyncIoCallback,\r
+                    EraseBlockEnd,\r
+                    &EraseBlockEnd->Event\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
+    }\r
+  } else {\r
+    EraseBlockEnd->Event = NULL;\r
+  }\r
+\r
+  Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlockEnd->Packet, EraseBlockEnd->Event);\r
+\r
+Error:\r
+  if ((Token != NULL) && (Token->Event != NULL)) {\r
+    //\r
+    // For asynchronous operation, only free request and event in error case.\r
+    // The request and event will be freed in asynchronous callback for success case.\r
+    //\r
+    if (EFI_ERROR (Status) && (EraseBlockEnd != NULL)) {\r
+      OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+      RemoveEntryList (&EraseBlockEnd->Link);\r
+      gBS->RestoreTPL (OldTpl);\r
+      if (EraseBlockEnd->Event != NULL) {\r
+        gBS->CloseEvent (EraseBlockEnd->Event);\r
+      }\r
+      FreePool (EraseBlockEnd);\r
+    }\r
+  } else {\r
+    //\r
+    // For synchronous operation, free request whatever the execution result is.\r
+    //\r
+    if (EraseBlockEnd != NULL) {\r
+      OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+      RemoveEntryList (&EraseBlockEnd->Link);\r
+      gBS->RestoreTPL (OldTpl);\r
+      FreePool (EraseBlockEnd);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Erase specified blocks through sync or async I/O request.\r
+\r
+  @param[in]  Device            A pointer to the SD_DEVICE instance.\r
+  @param[in]  Token             A pointer to the token associated with the transaction.\r
+  @param[in]  IsEnd             A boolean to show whether it's the last cmd in a series of cmds.\r
+                                This parameter is only meaningful in async I/O request.\r
+\r
+  @retval EFI_SUCCESS           The request is executed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be executed due to a lack of resources.\r
+  @retval Others                The request could not be executed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SdEraseBlock (\r
+  IN  SD_DEVICE                 *Device,\r
+  IN  EFI_BLOCK_IO2_TOKEN       *Token,\r
+  IN  BOOLEAN                   IsEnd\r
+  )\r
+{\r
+  EFI_STATUS                           Status;\r
+  EFI_SD_MMC_PASS_THRU_PROTOCOL        *PassThru;\r
+  SD_REQUEST                           *EraseBlock;\r
+  EFI_TPL                              OldTpl;\r
+\r
+  EraseBlock = NULL;\r
+  PassThru   = Device->Private->PassThru;\r
+\r
+  EraseBlock = AllocateZeroPool (sizeof (SD_REQUEST));\r
+  if (EraseBlock == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+\r
+  EraseBlock->Signature = SD_REQUEST_SIGNATURE;\r
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+  InsertTailList (&Device->Queue, &EraseBlock->Link);\r
+  gBS->RestoreTPL (OldTpl);\r
+  EraseBlock->Packet.SdMmcCmdBlk    = &EraseBlock->SdMmcCmdBlk;\r
+  EraseBlock->Packet.SdMmcStatusBlk = &EraseBlock->SdMmcStatusBlk;\r
+  EraseBlock->Packet.Timeout        = SD_GENERIC_TIMEOUT;\r
+\r
+  EraseBlock->SdMmcCmdBlk.CommandIndex = SD_ERASE;\r
+  EraseBlock->SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;\r
+  EraseBlock->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b;\r
+\r
+  EraseBlock->IsEnd = IsEnd;\r
+  EraseBlock->Token = Token;\r
+\r
+  if ((Token != NULL) && (Token->Event != NULL)) {\r
+    Status = gBS->CreateEvent (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_NOTIFY,\r
+                    AsyncIoCallback,\r
+                    EraseBlock,\r
+                    &EraseBlock->Event\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
+    }\r
+  } else {\r
+    EraseBlock->Event = NULL;\r
+  }\r
+\r
+  Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlock->Packet, EraseBlock->Event);\r
+\r
+Error:\r
+  if ((Token != NULL) && (Token->Event != NULL)) {\r
+    //\r
+    // For asynchronous operation, only free request and event in error case.\r
+    // The request and event will be freed in asynchronous callback for success case.\r
+    //\r
+    if (EFI_ERROR (Status) && (EraseBlock != NULL)) {\r
+      OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+      RemoveEntryList (&EraseBlock->Link);\r
+      gBS->RestoreTPL (OldTpl);\r
+      if (EraseBlock->Event != NULL) {\r
+        gBS->CloseEvent (EraseBlock->Event);\r
+      }\r
+      FreePool (EraseBlock);\r
+    }\r
+  } else {\r
+    //\r
+    // For synchronous operation, free request whatever the execution result is.\r
+    //\r
+    if (EraseBlock != NULL) {\r
+      OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+      RemoveEntryList (&EraseBlock->Link);\r
+      gBS->RestoreTPL (OldTpl);\r
+      FreePool (EraseBlock);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Erase a specified number of device blocks.\r
+\r
+  @param[in]       This           Indicates a pointer to the calling context.\r
+  @param[in]       MediaId        The media ID that the erase request is for.\r
+  @param[in]       Lba            The starting logical block address to be\r
+                                  erased. The caller is responsible for erasing\r
+                                  only legitimate locations.\r
+  @param[in, out]  Token          A pointer to the token associated with the\r
+                                  transaction.\r
+  @param[in]       Size           The size in bytes to be erased. This must be\r
+                                  a multiple of the physical block size of the\r
+                                  device.\r
+\r
+  @retval EFI_SUCCESS             The erase request was queued if Event is not\r
+                                  NULL. The data was erased correctly to the\r
+                                  device if the Event is NULL.to the device.\r
+  @retval EFI_WRITE_PROTECTED     The device cannot be erased due to write\r
+                                  protection.\r
+  @retval EFI_DEVICE_ERROR        The device reported an error while attempting\r
+                                  to perform the erase operation.\r
+  @retval EFI_INVALID_PARAMETER   The erase request contains LBAs that are not\r
+                                  valid.\r
+  @retval EFI_NO_MEDIA            There is no media in the device.\r
+  @retval EFI_MEDIA_CHANGED       The MediaId is not for the current media.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SdEraseBlocks (\r
+  IN     EFI_ERASE_BLOCK_PROTOCOL      *This,\r
+  IN     UINT32                        MediaId,\r
+  IN     EFI_LBA                       Lba,\r
+  IN OUT EFI_ERASE_BLOCK_TOKEN         *Token,\r
+  IN     UINTN                         Size\r
+  )\r
+{\r
+  EFI_STATUS                            Status;\r
+  EFI_BLOCK_IO_MEDIA                    *Media;\r
+  UINTN                                 BlockSize;\r
+  UINTN                                 BlockNum;\r
+  EFI_LBA                               LastLba;\r
+  SD_DEVICE                             *Device;\r
+\r
+  Status = EFI_SUCCESS;\r
+  Device = SD_DEVICE_DATA_FROM_ERASEBLK (This);\r
+  Media  = &Device->BlockMedia;\r
+\r
+  if (MediaId != Media->MediaId) {\r
+    return EFI_MEDIA_CHANGED;\r
+  }\r
+\r
+  if (Media->ReadOnly) {\r
+    return EFI_WRITE_PROTECTED;\r
+  }\r
+\r
+  //\r
+  // Check parameters.\r
+  //\r
+  BlockSize = Media->BlockSize;\r
+  if ((Size % BlockSize) != 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  BlockNum  = Size / BlockSize;\r
+  if ((Lba + BlockNum - 1) > Media->LastBlock) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((Token != NULL) && (Token->Event != NULL)) {\r
+    Token->TransactionStatus = EFI_SUCCESS;\r
+  }\r
+\r
+  LastLba = Lba + BlockNum - 1;\r
+\r
+  Status = SdEraseBlockStart (Device, Lba, (EFI_BLOCK_IO2_TOKEN*)Token, FALSE);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = SdEraseBlockEnd (Device, LastLba, (EFI_BLOCK_IO2_TOKEN*)Token, FALSE);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = SdEraseBlock (Device, (EFI_BLOCK_IO2_TOKEN*)Token, TRUE);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  DEBUG ((EFI_D_ERROR, "SdEraseBlocks(): Lba 0x%x BlkNo 0x%x Event %p with %r\n", Lba, BlockNum, Token->Event, Status));\r
+\r
+  return Status;\r
+}\r
 \r