Exemplo n.º 1
0
/**
  Discover all partitions in the EMMC device.

  @param[in] Device          The pointer to the EMMC_DEVICE data structure.

  @retval EFI_SUCCESS        All the partitions in the device are successfully enumerated.
  @return Others             Some error occurs when enumerating the partitions.

**/
EFI_STATUS
DiscoverAllPartitions (
  IN EMMC_DEVICE             *Device
  )
{
  EFI_STATUS                        Status;
  EMMC_PARTITION                    *Partition;
  EMMC_CSD                          *Csd;
  EMMC_CID                          *Cid;
  EMMC_EXT_CSD                      *ExtCsd;
  UINT8                             Slot;
  UINT64                            Capacity;
  UINT32                            DevStatus;
  UINT8                             Index;
  UINT32                            SecCount;
  UINT32                            GpSizeMult;

  Slot     = Device->Slot;

  Status = EmmcSendStatus (Device, Slot + 1, &DevStatus);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  //
  // Deselect the device to force it enter stby mode before getting CSD
  // register content.
  // Note here we don't judge return status as some EMMC devices return
  // error but the state has been stby.
  //
  EmmcSelect (Device, 0);

  Status = EmmcSendStatus (Device, Slot + 1, &DevStatus);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Csd    = &Device->Csd;
  Status = EmmcGetCsd (Device, Slot + 1, Csd);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  DumpCsd (Csd);

  if ((Csd->CSizeLow | Csd->CSizeHigh << 2) == 0xFFF) {
    Device->SectorAddressing = TRUE;
  } else {
    Device->SectorAddressing = FALSE;
  }

  Cid    = &Device->Cid;
  Status = EmmcGetCid (Device, Slot + 1, Cid);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Status = EmmcSelect (Device, Slot + 1);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  ExtCsd = &Device->ExtCsd;
  Status = EmmcGetExtCsd (Device, ExtCsd);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  DumpExtCsd (ExtCsd);

  if (ExtCsd->ExtCsdRev < 5) {
    DEBUG ((EFI_D_ERROR, "The EMMC device version is too low, we don't support!!!\n"));
    return EFI_UNSUPPORTED;
  }

  if ((ExtCsd->PartitioningSupport & BIT0) != BIT0) {
    DEBUG ((EFI_D_ERROR, "The EMMC device doesn't support Partition Feature!!!\n"));
    return EFI_UNSUPPORTED;
  }

  for (Index = 0; Index < EMMC_MAX_PARTITIONS; Index++) {
    Partition = &Device->Partition[Index];
    CopyMem (Partition, &mEmmcPartitionTemplate, sizeof (EMMC_PARTITION));
    Partition->Device             = Device;
    InitializeListHead (&Partition->Queue);
    Partition->BlockIo.Media      = &Partition->BlockMedia;
    Partition->BlockIo2.Media     = &Partition->BlockMedia;
    Partition->PartitionType      = Index;
    Partition->BlockMedia.IoAlign = Device->Private->PassThru->IoAlign;
    Partition->BlockMedia.BlockSize      = 0x200;
    Partition->BlockMedia.LastBlock      = 0x00;
    Partition->BlockMedia.RemovableMedia = FALSE;
    Partition->BlockMedia.MediaPresent     = TRUE;
    Partition->BlockMedia.LogicalPartition = FALSE;

    switch (Index) {
      case EmmcPartitionUserData:
        SecCount = *(UINT32*)&ExtCsd->SecCount;
        Capacity = MultU64x32 ((UINT64) SecCount, 0x200);
        break;
      case EmmcPartitionBoot1:
      case EmmcPartitionBoot2:
        Capacity = ExtCsd->BootSizeMult * SIZE_128KB;
        break;
      case EmmcPartitionRPMB:
        Capacity = ExtCsd->RpmbSizeMult * SIZE_128KB;
        break;
      case EmmcPartitionGP1:
        GpSizeMult = (UINT32)(ExtCsd->GpSizeMult[0] | (ExtCsd->GpSizeMult[1] << 8) | (ExtCsd->GpSizeMult[2] << 16));
        Capacity = MultU64x32 (MultU64x32 (MultU64x32 ((UINT64)GpSizeMult, ExtCsd->HcWpGrpSize), ExtCsd->HcEraseGrpSize), SIZE_512KB);
        break;
      case EmmcPartitionGP2:
        GpSizeMult = (UINT32)(ExtCsd->GpSizeMult[3] | (ExtCsd->GpSizeMult[4] << 8) | (ExtCsd->GpSizeMult[5] << 16));
        Capacity = MultU64x32 (MultU64x32 (MultU64x32 ((UINT64)GpSizeMult, ExtCsd->HcWpGrpSize), ExtCsd->HcEraseGrpSize), SIZE_512KB);
        break;
      case EmmcPartitionGP3:
        GpSizeMult = (UINT32)(ExtCsd->GpSizeMult[6] | (ExtCsd->GpSizeMult[7] << 8) | (ExtCsd->GpSizeMult[8] << 16));
        Capacity = MultU64x32 (MultU64x32 (MultU64x32 ((UINT64)GpSizeMult, ExtCsd->HcWpGrpSize), ExtCsd->HcEraseGrpSize), SIZE_512KB);
        break;
      case EmmcPartitionGP4:
        GpSizeMult = (UINT32)(ExtCsd->GpSizeMult[9] | (ExtCsd->GpSizeMult[10] << 8) | (ExtCsd->GpSizeMult[11] << 16));
        Capacity = MultU64x32 (MultU64x32 (MultU64x32 ((UINT64)GpSizeMult, ExtCsd->HcWpGrpSize), ExtCsd->HcEraseGrpSize), SIZE_512KB);
        break;
      default:
        ASSERT (FALSE);
        return EFI_INVALID_PARAMETER;
    }

    if (Capacity != 0) {
      Partition->Enable = TRUE;
      Partition->BlockMedia.LastBlock = DivU64x32 (Capacity, Partition->BlockMedia.BlockSize) - 1;
    }

    if ((ExtCsd->EraseGroupDef & BIT0) == 0) {
      if (Csd->WriteBlLen < 9) {
        Partition->EraseBlock.EraseLengthGranularity = 1;
      } else {
        Partition->EraseBlock.EraseLengthGranularity = (Csd->EraseGrpMult + 1) * (Csd->EraseGrpSize + 1) * (1 << (Csd->WriteBlLen - 9));
      }
    } else {
      Partition->EraseBlock.EraseLengthGranularity = 1024 * ExtCsd->HcEraseGrpSize;
    }
  }

  return EFI_SUCCESS;
}
Exemplo n.º 2
0
Arquivo: SdDxe.c Projeto: lersek/edk2
/**
  Discover user area partition in the SD device.

  @param[in] Device          The pointer to the SD_DEVICE data structure.

  @retval EFI_SUCCESS        The user area partition in the SD device is successfully identified.
  @return Others             Some error occurs when identifying the user area.

**/
EFI_STATUS
DiscoverUserArea (
  IN SD_DEVICE             *Device
  )
{
  EFI_STATUS                        Status;
  SD_CSD                            *Csd;
  SD_CSD2                           *Csd2;
  SD_CID                            *Cid;
  UINT64                            Capacity;
  UINT32                            DevStatus;
  UINT16                            Rca;
  UINT32                            CSize;
  UINT32                            CSizeMul;
  UINT32                            ReadBlLen;

  //
  // Deselect the device to force it enter stby mode.
  // Note here we don't judge return status as some SD devices return
  // error but the state has been stby.
  //
  SdSelect (Device, 0);

  Status = SdSetRca (Device, &Rca);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "DiscoverUserArea(): Assign new Rca = 0x%x fails with %r\n", Rca, Status));
    return Status;
  }

  Csd    = &Device->Csd;
  Status = SdGetCsd (Device, Rca, Csd);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  DumpCsd (Csd);

  Cid    = &Device->Cid;
  Status = SdGetCid (Device, Rca, Cid);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  GetSdModelName (Device, Cid);

  Status = SdSelect (Device, Rca);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "DiscoverUserArea(): Reselect the device 0x%x fails with %r\n", Rca, Status));
    return Status;
  }

  Status = SdSendStatus (Device, Rca, &DevStatus);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  if (Csd->CsdStructure == 0) {
    Device->SectorAddressing = FALSE;
    CSize     = (Csd->CSizeHigh << 2 | Csd->CSizeLow) + 1;
    CSizeMul  = (1 << (Csd->CSizeMul + 2));
    ReadBlLen = (1 << (Csd->ReadBlLen));
    Capacity  = MultU64x32 (MultU64x32 ((UINT64)CSize, CSizeMul), ReadBlLen);
  } else {
    Device->SectorAddressing = TRUE;
    Csd2      = (SD_CSD2*)(VOID*)Csd;
    CSize     = (Csd2->CSizeHigh << 16 | Csd2->CSizeLow) + 1;
    Capacity  = MultU64x32 ((UINT64)CSize, SIZE_512KB);
  }

  Device->BlockIo.Media               = &Device->BlockMedia;
  Device->BlockIo2.Media              = &Device->BlockMedia;
  Device->BlockMedia.IoAlign          = Device->Private->PassThru->IoAlign;
  Device->BlockMedia.BlockSize        = 0x200;
  Device->BlockMedia.LastBlock        = 0x00;
  Device->BlockMedia.RemovableMedia   = TRUE;
  Device->BlockMedia.MediaPresent     = TRUE;
  Device->BlockMedia.LogicalPartition = FALSE;
  Device->BlockMedia.LastBlock        = DivU64x32 (Capacity, Device->BlockMedia.BlockSize) - 1;

  if (Csd->EraseBlkEn) {
    Device->EraseBlock.EraseLengthGranularity = 1;
  } else {
    Device->EraseBlock.EraseLengthGranularity = (Csd->SectorSize + 1) * (1 << (Csd->WriteBlLen - 9));
  }

  return Status;
}