]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/Sd: add Erase Block support on sd/emmc device
authorFeng Tian <feng.tian@intel.com>
Tue, 3 May 2016 06:07:38 +0000 (14:07 +0800)
committerFeng Tian <feng.tian@intel.com>
Mon, 9 May 2016 08:18:01 +0000 (16:18 +0800)
It's done by producing EFI_ERASE_BLOCK_PROTOCOL protocol instance.

Cc: Hao Wu <hao.a.wu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Feng Tian <feng.tian@intel.com>
Reviewed-by: Hao Wu <hao.a.wu@intel.com>
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.h
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.c
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.h
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf
MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c
MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.h
MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c
MdeModulePkg/Bus/Sd/SdDxe/SdDxe.h
MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf

index edb438b09bfb0f95fea1491e0768f3add3b70ac8..5fe710dbb5d682ff1c1a93a6f4690250ec1ae555 100644 (file)
@@ -1589,3 +1589,416 @@ EmmcSecurityProtocolOut (
   return Status;\r
 }\r
 \r
+/**\r
+  Set the erase start address through sync or async I/O request.\r
+\r
+  @param[in]  Partition         A pointer to the EMMC_PARTITION 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
+EmmcEraseBlockStart (\r
+  IN  EMMC_PARTITION            *Partition,\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
+  EMMC_DEVICE                          *Device;\r
+  EMMC_REQUEST                         *EraseBlockStart;\r
+  EFI_TPL                              OldTpl;\r
+\r
+  EraseBlockStart = NULL;\r
+\r
+  Device   = Partition->Device;\r
+  PassThru = Device->Private->PassThru;\r
+\r
+  EraseBlockStart = AllocateZeroPool (sizeof (EMMC_REQUEST));\r
+  if (EraseBlockStart == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+\r
+  EraseBlockStart->Signature = EMMC_REQUEST_SIGNATURE;\r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+  InsertTailList (&Partition->Queue, &EraseBlockStart->Link);\r
+  gBS->RestoreTPL (OldTpl);\r
+  EraseBlockStart->Packet.SdMmcCmdBlk    = &EraseBlockStart->SdMmcCmdBlk;\r
+  EraseBlockStart->Packet.SdMmcStatusBlk = &EraseBlockStart->SdMmcStatusBlk;\r
+  EraseBlockStart->Packet.Timeout        = EMMC_GENERIC_TIMEOUT;\r
+\r
+  EraseBlockStart->SdMmcCmdBlk.CommandIndex = EMMC_ERASE_GROUP_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, Partition->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_CALLBACK,\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
+      RemoveEntryList (&EraseBlockStart->Link);\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
+      RemoveEntryList (&EraseBlockStart->Link);\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]  Partition         A pointer to the EMMC_PARTITION 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
+EmmcEraseBlockEnd (\r
+  IN  EMMC_PARTITION            *Partition,\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
+  EMMC_DEVICE                          *Device;\r
+  EMMC_REQUEST                         *EraseBlockEnd;\r
+  EFI_TPL                              OldTpl;\r
+\r
+  EraseBlockEnd = NULL;\r
+\r
+  Device   = Partition->Device;\r
+  PassThru = Device->Private->PassThru;\r
+\r
+  EraseBlockEnd = AllocateZeroPool (sizeof (EMMC_REQUEST));\r
+  if (EraseBlockEnd == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+\r
+  EraseBlockEnd->Signature = EMMC_REQUEST_SIGNATURE;\r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+  InsertTailList (&Partition->Queue, &EraseBlockEnd->Link);\r
+  gBS->RestoreTPL (OldTpl);\r
+  EraseBlockEnd->Packet.SdMmcCmdBlk    = &EraseBlockEnd->SdMmcCmdBlk;\r
+  EraseBlockEnd->Packet.SdMmcStatusBlk = &EraseBlockEnd->SdMmcStatusBlk;\r
+  EraseBlockEnd->Packet.Timeout        = EMMC_GENERIC_TIMEOUT;\r
+\r
+  EraseBlockEnd->SdMmcCmdBlk.CommandIndex = EMMC_ERASE_GROUP_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, Partition->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_CALLBACK,\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
+      RemoveEntryList (&EraseBlockEnd->Link);\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
+      RemoveEntryList (&EraseBlockEnd->Link);\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]  Partition         A pointer to the EMMC_PARTITION 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
+EmmcEraseBlock (\r
+  IN  EMMC_PARTITION            *Partition,\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
+  EMMC_DEVICE                          *Device;\r
+  EMMC_REQUEST                         *EraseBlock;\r
+  EFI_TPL                              OldTpl;\r
+\r
+  EraseBlock = NULL;\r
+\r
+  Device   = Partition->Device;\r
+  PassThru = Device->Private->PassThru;\r
+\r
+  EraseBlock = AllocateZeroPool (sizeof (EMMC_REQUEST));\r
+  if (EraseBlock == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+\r
+  EraseBlock->Signature = EMMC_REQUEST_SIGNATURE;\r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+  InsertTailList (&Partition->Queue, &EraseBlock->Link);\r
+  gBS->RestoreTPL (OldTpl);\r
+  EraseBlock->Packet.SdMmcCmdBlk    = &EraseBlock->SdMmcCmdBlk;\r
+  EraseBlock->Packet.SdMmcStatusBlk = &EraseBlock->SdMmcStatusBlk;\r
+  EraseBlock->Packet.Timeout        = EMMC_GENERIC_TIMEOUT;\r
+\r
+  EraseBlock->SdMmcCmdBlk.CommandIndex = EMMC_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_CALLBACK,\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
+      RemoveEntryList (&EraseBlock->Link);\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
+      RemoveEntryList (&EraseBlock->Link);\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
+EmmcEraseBlocks (\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
+  UINT8                                 PartitionConfig;\r
+  EMMC_PARTITION                        *Partition;\r
+  EMMC_DEVICE                           *Device;\r
+\r
+  Status    = EFI_SUCCESS;\r
+  Partition = EMMC_PARTITION_DATA_FROM_ERASEBLK (This);\r
+  Device    = Partition->Device;\r
+  Media     = &Partition->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
+  //\r
+  // Check if needs to switch partition access.\r
+  //\r
+  PartitionConfig = Device->ExtCsd.PartitionConfig;\r
+  if ((PartitionConfig & 0x7) != Partition->PartitionType) {\r
+    PartitionConfig &= (UINT8)~0x7;\r
+    PartitionConfig |= Partition->PartitionType;\r
+    Status = EmmcSetExtCsd (Partition, OFFSET_OF (EMMC_EXT_CSD, PartitionConfig), PartitionConfig, (EFI_BLOCK_IO2_TOKEN*)Token, FALSE);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    Device->ExtCsd.PartitionConfig = PartitionConfig;\r
+  }\r
+\r
+  Status = EmmcEraseBlockStart (Partition, Lba, (EFI_BLOCK_IO2_TOKEN*)Token, FALSE);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = EmmcEraseBlockEnd (Partition, LastLba, (EFI_BLOCK_IO2_TOKEN*)Token, FALSE);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = EmmcEraseBlock (Partition, (EFI_BLOCK_IO2_TOKEN*)Token, TRUE);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  DEBUG ((EFI_D_ERROR, "EmmcEraseBlocks(): Lba 0x%x BlkNo 0x%x Event %p with %r\n", Lba, BlockNum, Token->Event, Status));\r
+\r
+  return Status;\r
+}\r
+\r
index f0e1312b257a8c96361e995c31aed97afdb8806c..c8a6c5cab43ac2af12a4ebe19b4d7cbc2e66391a 100644 (file)
@@ -4,7 +4,7 @@
   This file defines common data structures, macro definitions and some module\r
   internal function header files.\r
 \r
-  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\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
@@ -462,5 +462,42 @@ EmmcSecurityProtocolOut (
   IN VOID                                     *PayloadBuffer\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
+EmmcEraseBlocks (\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
 #endif\r
 \r
index 2dd29814d925ddb6722827bda105eb30eea1ce54..6e156e9cc30bf3b496f8558f123b3b461fbfbfd4 100644 (file)
@@ -68,6 +68,11 @@ EMMC_PARTITION mEmmcPartitionTemplate = {
     EmmcSecurityProtocolIn,\r
     EmmcSecurityProtocolOut\r
   },\r
+  {                            // EraseBlock\r
+    EFI_ERASE_BLOCK_PROTOCOL_REVISION,\r
+    1,\r
+    EmmcEraseBlocks\r
+  },\r
   {\r
     NULL,\r
     NULL\r
@@ -369,6 +374,16 @@ DiscoverAllPartitions (
       Partition->Enable = TRUE;\r
       Partition->BlockMedia.LastBlock = DivU64x32 (Capacity, Partition->BlockMedia.BlockSize) - 1;\r
     }\r
+\r
+    if ((ExtCsd->EraseGroupDef & BIT0) == 0) {\r
+      if (Csd->WriteBlLen < 9) {\r
+        Partition->EraseBlock.EraseLengthGranularity = 1;\r
+      } else {\r
+        Partition->EraseBlock.EraseLengthGranularity = (Csd->EraseGrpMult + 1) * (Csd->EraseGrpSize + 1) * (1 << (Csd->WriteBlLen - 9));\r
+      }\r
+    } else {\r
+      Partition->EraseBlock.EraseLengthGranularity = 1024 * ExtCsd->HcEraseGrpSize;\r
+    }\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -438,10 +453,32 @@ InstallProtocolOnPartition (
                     &Partition->BlockIo2,\r
                     NULL\r
                     );\r
-   if (EFI_ERROR (Status)) {\r
+    if (EFI_ERROR (Status)) {\r
       goto Error;\r
     }\r
 \r
+    if (Partition->PartitionType != EmmcPartitionRPMB) {\r
+      Status = gBS->InstallProtocolInterface (\r
+                      &Partition->Handle,\r
+                      &gEfiEraseBlockProtocolGuid,\r
+                      EFI_NATIVE_INTERFACE,\r
+                      &Partition->EraseBlock\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        gBS->UninstallMultipleProtocolInterfaces (\r
+               &Partition->Handle,\r
+               &gEfiDevicePathProtocolGuid,\r
+               Partition->DevicePath,\r
+               &gEfiBlockIoProtocolGuid,\r
+               &Partition->BlockIo,\r
+               &gEfiBlockIo2ProtocolGuid,\r
+               &Partition->BlockIo2,\r
+               NULL\r
+               );\r
+        goto Error;\r
+      }\r
+    }\r
+\r
     if (((Partition->PartitionType == EmmcPartitionUserData) ||\r
         (Partition->PartitionType == EmmcPartitionBoot1) ||\r
         (Partition->PartitionType == EmmcPartitionBoot2)) &&\r
@@ -461,6 +498,8 @@ InstallProtocolOnPartition (
                &Partition->BlockIo,\r
                &gEfiBlockIo2ProtocolGuid,\r
                &Partition->BlockIo2,\r
+               &gEfiEraseBlockProtocolGuid,\r
+               &Partition->EraseBlock,\r
                NULL\r
                );\r
         goto Error;\r
@@ -954,6 +993,7 @@ EmmcDxeDriverBindingStop (
   EFI_BLOCK_IO_PROTOCOL                  *BlockIo;\r
   EFI_BLOCK_IO2_PROTOCOL                 *BlockIo2;\r
   EFI_STORAGE_SECURITY_COMMAND_PROTOCOL  *StorageSecurity;\r
+  EFI_ERASE_BLOCK_PROTOCOL               *EraseBlock;\r
   LIST_ENTRY                             *Link;\r
   LIST_ENTRY                             *NextLink;\r
   EMMC_REQUEST                           *Request;\r
@@ -1095,6 +1135,38 @@ EmmcDxeDriverBindingStop (
       continue;\r
     }\r
 \r
+    //\r
+    // If Erase Block Protocol is installed, then uninstall this protocol.\r
+    //\r
+    Status = gBS->OpenProtocol (\r
+                    ChildHandleBuffer[Index],\r
+                    &gEfiEraseBlockProtocolGuid,\r
+                    (VOID **) &EraseBlock,\r
+                    This->DriverBindingHandle,\r
+                    Controller,\r
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                    );\r
+\r
+    if (!EFI_ERROR (Status)) {\r
+      Status = gBS->UninstallProtocolInterface (\r
+                      ChildHandleBuffer[Index],\r
+                      &gEfiEraseBlockProtocolGuid,\r
+                      &Partition->EraseBlock\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        gBS->OpenProtocol (\r
+          Controller,\r
+          &gEfiSdMmcPassThruProtocolGuid,\r
+          (VOID **) &Partition->Device->Private->PassThru,\r
+          This->DriverBindingHandle,\r
+          ChildHandleBuffer[Index],\r
+          EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+          );\r
+        AllChildrenStopped = FALSE;\r
+        continue;\r
+      }\r
+    }\r
+\r
     //\r
     // If Storage Security Command Protocol is installed, then uninstall this protocol.\r
     //\r
index 0c50d62eb799fb52a0bb9e6f1eafd2c4741fbb01..0ae4eccac6ea0d991009b1c7affafaf7495c2af2 100644 (file)
@@ -25,6 +25,7 @@
 #include <Protocol/BlockIo.h>\r
 #include <Protocol/BlockIo2.h>\r
 #include <Protocol/StorageSecurityCommand.h>\r
+#include <Protocol/EraseBlock.h>\r
 \r
 #include <Protocol/DevicePath.h>\r
 \r
@@ -57,6 +58,9 @@ extern EFI_COMPONENT_NAME2_PROTOCOL     gEmmcDxeComponentName2;
 #define EMMC_PARTITION_DATA_FROM_SSP(a) \\r
     CR(a, EMMC_PARTITION, StorageSecurity, EMMC_PARTITION_SIGNATURE)\r
 \r
+#define EMMC_PARTITION_DATA_FROM_ERASEBLK(a) \\r
+    CR(a, EMMC_PARTITION, EraseBlock, EMMC_PARTITION_SIGNATURE)\r
+\r
 //\r
 // Take 2.5 seconds as generic time out value, 1 microsecond as unit.\r
 //\r
@@ -97,6 +101,7 @@ typedef struct {
   EFI_BLOCK_IO2_PROTOCOL                BlockIo2;\r
   EFI_BLOCK_IO_MEDIA                    BlockMedia;\r
   EFI_STORAGE_SECURITY_COMMAND_PROTOCOL StorageSecurity;\r
+  EFI_ERASE_BLOCK_PROTOCOL              EraseBlock;\r
 \r
   LIST_ENTRY                            Queue;\r
 \r
index a10bcd234371e189f39dbd947722feedb0359774..7b0504937a6d45098fea7dc571466efaf353296e 100644 (file)
@@ -4,7 +4,7 @@
 #  It produces BlockIo, BlockIo2 and StorageSecurity protocols to allow upper layer\r
 #  access the EMMC device.\r
 #\r
-#  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
 #\r
 #  This program and the accompanying materials\r
 #  are licensed and made available under the terms and conditions of the BSD License\r
@@ -60,6 +60,7 @@
   gEfiBlockIoProtocolGuid                      ## BY_START\r
   gEfiBlockIo2ProtocolGuid                     ## BY_START\r
   gEfiStorageSecurityCommandProtocolGuid       ## SOMETIMES_PRODUCES\r
+  gEfiEraseBlockProtocolGuid                   ## BY_START\r
   ## TO_START\r
   ## BY_START\r
   gEfiDevicePathProtocolGuid\r
index b7a5fe49ae1c2dc89a4c2a9dbd954afd9a16d0e3..d8b9459c63c343bc02492146333948d1129b985c 100644 (file)
@@ -970,4 +970,390 @@ 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_CALLBACK);\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_CALLBACK,\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
+      RemoveEntryList (&EraseBlockStart->Link);\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
+      RemoveEntryList (&EraseBlockStart->Link);\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_CALLBACK);\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_CALLBACK,\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
+      RemoveEntryList (&EraseBlockEnd->Link);\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
+      RemoveEntryList (&EraseBlockEnd->Link);\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_CALLBACK);\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_CALLBACK,\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
+      RemoveEntryList (&EraseBlock->Link);\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
+      RemoveEntryList (&EraseBlock->Link);\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
index 36e20dee7254eeb9674150b6b9336e256ed18923..227b45bebf5082c8b95ad01c3af3a20de7d2928f 100644 (file)
@@ -4,7 +4,7 @@
   This file defines common data structures, macro definitions and some module\r
   internal function header files.\r
 \r
-  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\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
@@ -217,5 +217,42 @@ SdFlushBlocksEx (
   IN OUT EFI_BLOCK_IO2_TOKEN     *Token\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
 #endif\r
 \r
index 7ed80b6bd05b81e9827dcec5193cc4b17a070ef5..f657fb9c6e9916cc0b3c0fd96e768e7b112132b2 100644 (file)
@@ -64,6 +64,11 @@ SD_DEVICE mSdDeviceTemplate = {
     0,                         // IoAlign\r
     0                          // LastBlock\r
   },\r
+  {                            // EraseBlock\r
+    EFI_ERASE_BLOCK_PROTOCOL_REVISION,\r
+    1,\r
+    SdEraseBlocks\r
+  },\r
   {                            // Queue\r
     NULL,\r
     NULL\r
@@ -247,6 +252,12 @@ DiscoverUserArea (
   Device->BlockMedia.LogicalPartition = FALSE;\r
   Device->BlockMedia.LastBlock        = DivU64x32 (Capacity, Device->BlockMedia.BlockSize) - 1;\r
 \r
+  if (Csd->EraseBlkEn) {\r
+    Device->EraseBlock.EraseLengthGranularity = 1;\r
+  } else {\r
+    Device->EraseBlock.EraseLengthGranularity = (Csd->SectorSize + 1) * (1 << (Csd->WriteBlLen - 9));\r
+  }\r
+\r
   return Status;\r
 }\r
 \r
@@ -369,6 +380,8 @@ DiscoverSdDevice (
                   &Device->BlockIo,\r
                   &gEfiBlockIo2ProtocolGuid,\r
                   &Device->BlockIo2,\r
+                  &gEfiEraseBlockProtocolGuid,\r
+                  &Device->EraseBlock,\r
                   NULL\r
                   );\r
 \r
@@ -825,6 +838,8 @@ SdDxeDriverBindingStop (
                     &Device->BlockIo,\r
                     &gEfiBlockIo2ProtocolGuid,\r
                     &Device->BlockIo2,\r
+                    &gEfiEraseBlockProtocolGuid,\r
+                    &Device->EraseBlock,\r
                     NULL\r
                     );\r
     if (EFI_ERROR (Status)) {\r
index ca1609e900d07cee0cda27b2bb23c1a1ebaf4eb0..0ba72b7f9ce1977e9112491b52d94a8df0dd4981 100644 (file)
@@ -4,7 +4,7 @@
   This file defines common data structures, macro definitions and some module\r
   internal function header files.\r
 \r
-  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\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
@@ -24,6 +24,7 @@
 #include <Protocol/SdMmcPassThru.h>\r
 #include <Protocol/BlockIo.h>\r
 #include <Protocol/BlockIo2.h>\r
+#include <Protocol/EraseBlock.h>\r
 \r
 #include <Protocol/DevicePath.h>\r
 \r
@@ -53,6 +54,9 @@ extern EFI_COMPONENT_NAME2_PROTOCOL     gSdDxeComponentName2;
 #define SD_DEVICE_DATA_FROM_BLKIO2(a) \\r
     CR(a, SD_DEVICE, BlockIo2, SD_DEVICE_SIGNATURE)\r
 \r
+#define SD_DEVICE_DATA_FROM_ERASEBLK(a) \\r
+    CR(a, SD_DEVICE, EraseBlock, SD_DEVICE_SIGNATURE)\r
+\r
 //\r
 // Take 2.5 seconds as generic time out value, 1 microsecond as unit.\r
 //\r
@@ -95,6 +99,7 @@ struct _SD_DEVICE {
   EFI_BLOCK_IO_PROTOCOL                 BlockIo;\r
   EFI_BLOCK_IO2_PROTOCOL                BlockIo2;\r
   EFI_BLOCK_IO_MEDIA                    BlockMedia;\r
+  EFI_ERASE_BLOCK_PROTOCOL              EraseBlock;\r
 \r
   LIST_ENTRY                            Queue;\r
 \r
index b24b721236d9364a5d6d2526d076d76f195a5b68..6f5e6ca72eaa3031ed0394ab53a894afa4aec4ad 100644 (file)
@@ -4,7 +4,7 @@
 #  It produces BlockIo and BlockIo2 protocols to allow upper layer\r
 #  access the SD memory card device.\r
 #\r
-#  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
 #\r
 #  This program and the accompanying materials\r
 #  are licensed and made available under the terms and conditions of the BSD License\r
@@ -59,6 +59,7 @@
   gEfiSdMmcPassThruProtocolGuid                ## TO_START\r
   gEfiBlockIoProtocolGuid                      ## BY_START\r
   gEfiBlockIo2ProtocolGuid                     ## BY_START\r
+  gEfiEraseBlockProtocolGuid                   ## BY_START\r
   ## TO_START\r
   ## BY_START\r
   gEfiDevicePathProtocolGuid\r