Home | History | Annotate | Download | only in SdBlockIoPei
      1 /** @file
      2 
      3   Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
      4   This program and the accompanying materials
      5   are licensed and made available under the terms and conditions of the BSD License
      6   which accompanies this distribution.  The full text of the license may be found at
      7   http://opensource.org/licenses/bsd-license.php
      8 
      9   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 **/
     13 
     14 #include "SdBlockIoPei.h"
     15 
     16 //
     17 // Template for SD HC Slot Data.
     18 //
     19 SD_PEIM_HC_SLOT   gSdHcSlotTemplate = {
     20   SD_PEIM_SLOT_SIG,               // Signature
     21   {                               // Media
     22     MSG_SD_DP,
     23     FALSE,
     24     TRUE,
     25     FALSE,
     26     0x200,
     27     0
     28   },
     29   0,                              // SdHcBase
     30   {                               // Capability
     31     0,
     32   },
     33   {                               // Csd
     34     0,
     35   },
     36   TRUE,                           // SectorAddressing
     37   NULL                            // Private
     38 };
     39 
     40 //
     41 // Template for SD HC Private Data.
     42 //
     43 SD_PEIM_HC_PRIVATE_DATA gSdHcPrivateTemplate = {
     44   SD_PEIM_SIG,                    // Signature
     45   NULL,                           // Pool
     46   {                               // BlkIoPpi
     47     SdBlockIoPeimGetDeviceNo,
     48     SdBlockIoPeimGetMediaInfo,
     49     SdBlockIoPeimReadBlocks
     50   },
     51   {                               // BlkIo2Ppi
     52     EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION,
     53     SdBlockIoPeimGetDeviceNo2,
     54     SdBlockIoPeimGetMediaInfo2,
     55     SdBlockIoPeimReadBlocks2
     56   },
     57   {                               // BlkIoPpiList
     58     EFI_PEI_PPI_DESCRIPTOR_PPI,
     59     &gEfiPeiVirtualBlockIoPpiGuid,
     60     NULL
     61   },
     62   {                               // BlkIo2PpiList
     63     EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
     64     &gEfiPeiVirtualBlockIo2PpiGuid,
     65     NULL
     66   },
     67   {                               // Slot
     68     {
     69       0,
     70     },
     71     {
     72       0,
     73     },
     74     {
     75       0,
     76     },
     77     {
     78       0,
     79     },
     80     {
     81       0,
     82     },
     83     {
     84       0,
     85     }
     86   },
     87   0,                              // SlotNum
     88   0                               // TotalBlkIoDevices
     89 };
     90 /**
     91   Gets the count of block I/O devices that one specific block driver detects.
     92 
     93   This function is used for getting the count of block I/O devices that one
     94   specific block driver detects.  To the PEI ATAPI driver, it returns the number
     95   of all the detected ATAPI devices it detects during the enumeration process.
     96   To the PEI legacy floppy driver, it returns the number of all the legacy
     97   devices it finds during its enumeration process. If no device is detected,
     98   then the function will return zero.
     99 
    100   @param[in]  PeiServices          General-purpose services that are available
    101                                    to every PEIM.
    102   @param[in]  This                 Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
    103                                    instance.
    104   @param[out] NumberBlockDevices   The number of block I/O devices discovered.
    105 
    106   @retval     EFI_SUCCESS          The operation performed successfully.
    107 
    108 **/
    109 EFI_STATUS
    110 EFIAPI
    111 SdBlockIoPeimGetDeviceNo (
    112   IN  EFI_PEI_SERVICES               **PeiServices,
    113   IN  EFI_PEI_RECOVERY_BLOCK_IO_PPI  *This,
    114   OUT UINTN                          *NumberBlockDevices
    115   )
    116 {
    117   SD_PEIM_HC_PRIVATE_DATA            *Private;
    118 
    119   Private = GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);
    120   *NumberBlockDevices = Private->TotalBlkIoDevices;
    121   return EFI_SUCCESS;
    122 }
    123 
    124 /**
    125   Gets a block device's media information.
    126 
    127   This function will provide the caller with the specified block device's media
    128   information. If the media changes, calling this function will update the media
    129   information accordingly.
    130 
    131   @param[in]  PeiServices   General-purpose services that are available to every
    132                             PEIM
    133   @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
    134   @param[in]  DeviceIndex   Specifies the block device to which the function wants
    135                             to talk. Because the driver that implements Block I/O
    136                             PPIs will manage multiple block devices, the PPIs that
    137                             want to talk to a single device must specify the
    138                             device index that was assigned during the enumeration
    139                             process. This index is a number from one to
    140                             NumberBlockDevices.
    141   @param[out] MediaInfo     The media information of the specified block media.
    142                             The caller is responsible for the ownership of this
    143                             data structure.
    144 
    145   @par Note:
    146       The MediaInfo structure describes an enumeration of possible block device
    147       types.  This enumeration exists because no device paths are actually passed
    148       across interfaces that describe the type or class of hardware that is publishing
    149       the block I/O interface. This enumeration will allow for policy decisions
    150       in the Recovery PEIM, such as "Try to recover from legacy floppy first,
    151       LS-120 second, CD-ROM third." If there are multiple partitions abstracted
    152       by a given device type, they should be reported in ascending order; this
    153       order also applies to nested partitions, such as legacy MBR, where the
    154       outermost partitions would have precedence in the reporting order. The
    155       same logic applies to systems such as IDE that have precedence relationships
    156       like "Master/Slave" or "Primary/Secondary". The master device should be
    157       reported first, the slave second.
    158 
    159   @retval EFI_SUCCESS        Media information about the specified block device
    160                              was obtained successfully.
    161   @retval EFI_DEVICE_ERROR   Cannot get the media information due to a hardware
    162                              error.
    163 
    164 **/
    165 EFI_STATUS
    166 EFIAPI
    167 SdBlockIoPeimGetMediaInfo (
    168   IN  EFI_PEI_SERVICES               **PeiServices,
    169   IN  EFI_PEI_RECOVERY_BLOCK_IO_PPI  *This,
    170   IN  UINTN                          DeviceIndex,
    171   OUT EFI_PEI_BLOCK_IO_MEDIA         *MediaInfo
    172   )
    173 {
    174   SD_PEIM_HC_PRIVATE_DATA            *Private;
    175 
    176   Private   = GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);
    177 
    178   if ((DeviceIndex == 0) || (DeviceIndex > Private->TotalBlkIoDevices)) {
    179     return EFI_INVALID_PARAMETER;
    180   }
    181 
    182   MediaInfo->DeviceType   = SD;
    183   MediaInfo->MediaPresent = TRUE;
    184   MediaInfo->LastBlock    = (UINTN)Private->Slot[DeviceIndex - 1].Media.LastBlock;
    185   MediaInfo->BlockSize    = Private->Slot[DeviceIndex - 1].Media.BlockSize;
    186 
    187   return EFI_SUCCESS;
    188 }
    189 
    190 /**
    191   Reads the requested number of blocks from the specified block device.
    192 
    193   The function reads the requested number of blocks from the device. All the
    194   blocks are read, or an error is returned. If there is no media in the device,
    195   the function returns EFI_NO_MEDIA.
    196 
    197   @param[in]  PeiServices   General-purpose services that are available to
    198                             every PEIM.
    199   @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
    200   @param[in]  DeviceIndex   Specifies the block device to which the function wants
    201                             to talk. Because the driver that implements Block I/O
    202                             PPIs will manage multiple block devices, PPIs that
    203                             want to talk to a single device must specify the device
    204                             index that was assigned during the enumeration process.
    205                             This index is a number from one to NumberBlockDevices.
    206   @param[in]  StartLBA      The starting logical block address (LBA) to read from
    207                             on the device
    208   @param[in]  BufferSize    The size of the Buffer in bytes. This number must be
    209                             a multiple of the intrinsic block size of the device.
    210   @param[out] Buffer        A pointer to the destination buffer for the data.
    211                             The caller is responsible for the ownership of the
    212                             buffer.
    213 
    214   @retval EFI_SUCCESS             The data was read correctly from the device.
    215   @retval EFI_DEVICE_ERROR        The device reported an error while attempting
    216                                   to perform the read operation.
    217   @retval EFI_INVALID_PARAMETER   The read request contains LBAs that are not
    218                                   valid, or the buffer is not properly aligned.
    219   @retval EFI_NO_MEDIA            There is no media in the device.
    220   @retval EFI_BAD_BUFFER_SIZE     The BufferSize parameter is not a multiple of
    221                                   the intrinsic block size of the device.
    222 
    223 **/
    224 EFI_STATUS
    225 EFIAPI
    226 SdBlockIoPeimReadBlocks (
    227   IN  EFI_PEI_SERVICES               **PeiServices,
    228   IN  EFI_PEI_RECOVERY_BLOCK_IO_PPI  *This,
    229   IN  UINTN                          DeviceIndex,
    230   IN  EFI_PEI_LBA                    StartLBA,
    231   IN  UINTN                          BufferSize,
    232   OUT VOID                           *Buffer
    233   )
    234 {
    235   EFI_STATUS                         Status;
    236   UINT32                             BlockSize;
    237   UINTN                              NumberOfBlocks;
    238   SD_PEIM_HC_PRIVATE_DATA            *Private;
    239   UINTN                              Remaining;
    240   UINT32                             MaxBlock;
    241 
    242   Status  = EFI_SUCCESS;
    243   Private = GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);
    244 
    245   //
    246   // Check parameters
    247   //
    248   if (Buffer == NULL) {
    249     return EFI_INVALID_PARAMETER;
    250   }
    251 
    252   if (BufferSize == 0) {
    253     return EFI_SUCCESS;
    254   }
    255 
    256   if ((DeviceIndex == 0) || (DeviceIndex > Private->TotalBlkIoDevices)) {
    257     return EFI_INVALID_PARAMETER;
    258   }
    259 
    260   BlockSize = Private->Slot[DeviceIndex - 1].Media.BlockSize;
    261   if (BufferSize % BlockSize != 0) {
    262     return EFI_BAD_BUFFER_SIZE;
    263   }
    264 
    265   if (StartLBA > Private->Slot[DeviceIndex - 1].Media.LastBlock) {
    266     return EFI_INVALID_PARAMETER;
    267   }
    268 
    269   NumberOfBlocks = BufferSize / BlockSize;
    270 
    271   //
    272   // Start to execute data transfer. The max block number in single cmd is 65535 blocks.
    273   //
    274   Remaining = NumberOfBlocks;
    275   MaxBlock  = 0xFFFF;
    276 
    277   while (Remaining > 0) {
    278     if (Remaining <= MaxBlock) {
    279       NumberOfBlocks = Remaining;
    280     } else {
    281       NumberOfBlocks = MaxBlock;
    282     }
    283 
    284     BufferSize = NumberOfBlocks * BlockSize;
    285     if (NumberOfBlocks != 1) {
    286       Status = SdPeimRwMultiBlocks (&Private->Slot[DeviceIndex - 1], StartLBA, BlockSize, Buffer, BufferSize, TRUE);
    287     } else {
    288       Status = SdPeimRwSingleBlock (&Private->Slot[DeviceIndex - 1], StartLBA, BlockSize, Buffer, BufferSize, TRUE);
    289     }
    290     if (EFI_ERROR (Status)) {
    291       return Status;
    292     }
    293 
    294     StartLBA  += NumberOfBlocks;
    295     Buffer     = (UINT8*)Buffer + BufferSize;
    296     Remaining -= NumberOfBlocks;
    297   }
    298   return Status;
    299 }
    300 
    301 /**
    302   Gets the count of block I/O devices that one specific block driver detects.
    303 
    304   This function is used for getting the count of block I/O devices that one
    305   specific block driver detects.  To the PEI ATAPI driver, it returns the number
    306   of all the detected ATAPI devices it detects during the enumeration process.
    307   To the PEI legacy floppy driver, it returns the number of all the legacy
    308   devices it finds during its enumeration process. If no device is detected,
    309   then the function will return zero.
    310 
    311   @param[in]  PeiServices          General-purpose services that are available
    312                                    to every PEIM.
    313   @param[in]  This                 Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI
    314                                    instance.
    315   @param[out] NumberBlockDevices   The number of block I/O devices discovered.
    316 
    317   @retval     EFI_SUCCESS          The operation performed successfully.
    318 
    319 **/
    320 EFI_STATUS
    321 EFIAPI
    322 SdBlockIoPeimGetDeviceNo2 (
    323   IN  EFI_PEI_SERVICES               **PeiServices,
    324   IN  EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
    325   OUT UINTN                          *NumberBlockDevices
    326   )
    327 {
    328   SD_PEIM_HC_PRIVATE_DATA   *Private;
    329 
    330   Private = GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);
    331   *NumberBlockDevices = Private->TotalBlkIoDevices;
    332 
    333   return EFI_SUCCESS;
    334 }
    335 
    336 /**
    337   Gets a block device's media information.
    338 
    339   This function will provide the caller with the specified block device's media
    340   information. If the media changes, calling this function will update the media
    341   information accordingly.
    342 
    343   @param[in]  PeiServices   General-purpose services that are available to every
    344                             PEIM
    345   @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.
    346   @param[in]  DeviceIndex   Specifies the block device to which the function wants
    347                             to talk. Because the driver that implements Block I/O
    348                             PPIs will manage multiple block devices, the PPIs that
    349                             want to talk to a single device must specify the
    350                             device index that was assigned during the enumeration
    351                             process. This index is a number from one to
    352                             NumberBlockDevices.
    353   @param[out] MediaInfo     The media information of the specified block media.
    354                             The caller is responsible for the ownership of this
    355                             data structure.
    356 
    357   @par Note:
    358       The MediaInfo structure describes an enumeration of possible block device
    359       types.  This enumeration exists because no device paths are actually passed
    360       across interfaces that describe the type or class of hardware that is publishing
    361       the block I/O interface. This enumeration will allow for policy decisions
    362       in the Recovery PEIM, such as "Try to recover from legacy floppy first,
    363       LS-120 second, CD-ROM third." If there are multiple partitions abstracted
    364       by a given device type, they should be reported in ascending order; this
    365       order also applies to nested partitions, such as legacy MBR, where the
    366       outermost partitions would have precedence in the reporting order. The
    367       same logic applies to systems such as IDE that have precedence relationships
    368       like "Master/Slave" or "Primary/Secondary". The master device should be
    369       reported first, the slave second.
    370 
    371   @retval EFI_SUCCESS        Media information about the specified block device
    372                              was obtained successfully.
    373   @retval EFI_DEVICE_ERROR   Cannot get the media information due to a hardware
    374                              error.
    375 
    376 **/
    377 EFI_STATUS
    378 EFIAPI
    379 SdBlockIoPeimGetMediaInfo2 (
    380   IN  EFI_PEI_SERVICES               **PeiServices,
    381   IN  EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
    382   IN  UINTN                          DeviceIndex,
    383   OUT EFI_PEI_BLOCK_IO2_MEDIA        *MediaInfo
    384   )
    385 {
    386   EFI_STATUS                         Status;
    387   SD_PEIM_HC_PRIVATE_DATA            *Private;
    388   EFI_PEI_BLOCK_IO_MEDIA             Media;
    389 
    390   Private = GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);
    391 
    392   Status  = SdBlockIoPeimGetMediaInfo (
    393               PeiServices,
    394               &Private->BlkIoPpi,
    395               DeviceIndex,
    396               &Media
    397               );
    398   if (EFI_ERROR (Status)) {
    399     return Status;
    400   }
    401 
    402   CopyMem (MediaInfo, &(Private->Slot[DeviceIndex - 1].Media), sizeof (EFI_PEI_BLOCK_IO2_MEDIA));
    403   return EFI_SUCCESS;
    404 }
    405 
    406 /**
    407   Reads the requested number of blocks from the specified block device.
    408 
    409   The function reads the requested number of blocks from the device. All the
    410   blocks are read, or an error is returned. If there is no media in the device,
    411   the function returns EFI_NO_MEDIA.
    412 
    413   @param[in]  PeiServices   General-purpose services that are available to
    414                             every PEIM.
    415   @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.
    416   @param[in]  DeviceIndex   Specifies the block device to which the function wants
    417                             to talk. Because the driver that implements Block I/O
    418                             PPIs will manage multiple block devices, PPIs that
    419                             want to talk to a single device must specify the device
    420                             index that was assigned during the enumeration process.
    421                             This index is a number from one to NumberBlockDevices.
    422   @param[in]  StartLBA      The starting logical block address (LBA) to read from
    423                             on the device
    424   @param[in]  BufferSize    The size of the Buffer in bytes. This number must be
    425                             a multiple of the intrinsic block size of the device.
    426   @param[out] Buffer        A pointer to the destination buffer for the data.
    427                             The caller is responsible for the ownership of the
    428                             buffer.
    429 
    430   @retval EFI_SUCCESS             The data was read correctly from the device.
    431   @retval EFI_DEVICE_ERROR        The device reported an error while attempting
    432                                   to perform the read operation.
    433   @retval EFI_INVALID_PARAMETER   The read request contains LBAs that are not
    434                                   valid, or the buffer is not properly aligned.
    435   @retval EFI_NO_MEDIA            There is no media in the device.
    436   @retval EFI_BAD_BUFFER_SIZE     The BufferSize parameter is not a multiple of
    437                                   the intrinsic block size of the device.
    438 
    439 **/
    440 EFI_STATUS
    441 EFIAPI
    442 SdBlockIoPeimReadBlocks2 (
    443   IN  EFI_PEI_SERVICES               **PeiServices,
    444   IN  EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
    445   IN  UINTN                          DeviceIndex,
    446   IN  EFI_PEI_LBA                    StartLBA,
    447   IN  UINTN                          BufferSize,
    448   OUT VOID                           *Buffer
    449   )
    450 {
    451   EFI_STATUS                         Status;
    452   SD_PEIM_HC_PRIVATE_DATA            *Private;
    453 
    454   Status    = EFI_SUCCESS;
    455   Private   = GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);
    456 
    457   Status  = SdBlockIoPeimReadBlocks (
    458               PeiServices,
    459               &Private->BlkIoPpi,
    460               DeviceIndex,
    461               StartLBA,
    462               BufferSize,
    463               Buffer
    464               );
    465   return Status;
    466 }
    467 
    468 /**
    469   The user code starts with this function.
    470 
    471   @param  FileHandle             Handle of the file being invoked.
    472   @param  PeiServices            Describes the list of possible PEI Services.
    473 
    474   @retval EFI_SUCCESS            The driver is successfully initialized.
    475   @retval Others                 Can't initialize the driver.
    476 
    477 **/
    478 EFI_STATUS
    479 EFIAPI
    480 InitializeSdBlockIoPeim (
    481   IN EFI_PEI_FILE_HANDLE        FileHandle,
    482   IN CONST EFI_PEI_SERVICES     **PeiServices
    483   )
    484 {
    485   EFI_STATUS                       Status;
    486   SD_PEIM_HC_PRIVATE_DATA          *Private;
    487   EDKII_SD_MMC_HOST_CONTROLLER_PPI *SdMmcHcPpi;
    488   UINT32                           Index;
    489   UINTN                            *MmioBase;
    490   UINT8                            BarNum;
    491   UINT8                            SlotNum;
    492   UINT8                            Controller;
    493   UINT64                           Capacity;
    494   SD_HC_SLOT_CAP                   Capability;
    495   SD_PEIM_HC_SLOT                  *Slot;
    496   SD_CSD                           *Csd;
    497   SD_CSD2                          *Csd2;
    498   UINT32                           CSize;
    499   UINT32                           CSizeMul;
    500   UINT32                           ReadBlLen;
    501 
    502   //
    503   // Shadow this PEIM to run from memory
    504   //
    505   if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
    506     return EFI_SUCCESS;
    507   }
    508 
    509   //
    510   // locate Sd host controller PPI
    511   //
    512   Status = PeiServicesLocatePpi (
    513              &gEdkiiPeiSdMmcHostControllerPpiGuid,
    514              0,
    515              NULL,
    516              (VOID **) &SdMmcHcPpi
    517              );
    518   if (EFI_ERROR (Status)) {
    519     return EFI_DEVICE_ERROR;
    520   }
    521 
    522   Controller = 0;
    523   MmioBase   = NULL;
    524   while (TRUE) {
    525     Status = SdMmcHcPpi->GetSdMmcHcMmioBar (SdMmcHcPpi, Controller, &MmioBase, &BarNum);
    526     //
    527     // When status is error, meant no controller is found
    528     //
    529     if (EFI_ERROR (Status)) {
    530       break;
    531     }
    532 
    533     if (BarNum == 0) {
    534       Controller++;
    535       continue;
    536     }
    537 
    538     Private = AllocateCopyPool (sizeof (SD_PEIM_HC_PRIVATE_DATA), &gSdHcPrivateTemplate);
    539     if (Private == NULL) {
    540       Status = EFI_OUT_OF_RESOURCES;
    541       break;
    542     }
    543     Private->BlkIoPpiList.Ppi  = (VOID*)&Private->BlkIoPpi;
    544     Private->BlkIo2PpiList.Ppi = (VOID*)&Private->BlkIo2Ppi;
    545     //
    546     // Initialize the memory pool which will be used in all transactions.
    547     //
    548     Status = SdPeimInitMemPool (Private);
    549     if (EFI_ERROR (Status)) {
    550       Status = EFI_OUT_OF_RESOURCES;
    551       break;
    552     }
    553 
    554     for (Index = 0; Index < BarNum; Index++) {
    555       Status = SdPeimHcGetCapability (MmioBase[Index], &Capability);
    556       if (EFI_ERROR (Status)) {
    557         continue;
    558       }
    559       if (Capability.SlotType != 0x1) {
    560         DEBUG ((EFI_D_INFO, "The slot at 0x%x is not embedded slot type\n", MmioBase[Index]));
    561         Status = EFI_UNSUPPORTED;
    562         continue;
    563       }
    564 
    565       Status = SdPeimHcReset (MmioBase[Index]);
    566       if (EFI_ERROR (Status)) {
    567         continue;
    568       }
    569       Status = SdPeimHcCardDetect (MmioBase[Index]);
    570       if (EFI_ERROR (Status)) {
    571         continue;
    572       }
    573       Status = SdPeimHcInitHost (MmioBase[Index]);
    574       if (EFI_ERROR (Status)) {
    575         continue;
    576       }
    577 
    578       SlotNum = Private->SlotNum;
    579       Slot    = &Private->Slot[SlotNum];
    580       CopyMem (Slot, &gSdHcSlotTemplate, sizeof (SD_PEIM_HC_SLOT));
    581       Slot->Private  = Private;
    582       Slot->SdHcBase = MmioBase[Index];
    583       CopyMem (&Slot->Capability, &Capability, sizeof (Capability));
    584 
    585       Status = SdPeimIdentification (Slot);
    586       if (EFI_ERROR (Status)) {
    587         continue;
    588       }
    589 
    590       Csd = &Slot->Csd;
    591       if (Csd->CsdStructure == 0) {
    592         Slot->SectorAddressing = FALSE;
    593         CSize     = (Csd->CSizeHigh << 2 | Csd->CSizeLow) + 1;
    594         CSizeMul  = (1 << (Csd->CSizeMul + 2));
    595         ReadBlLen = (1 << (Csd->ReadBlLen));
    596         Capacity  = MultU64x32 (MultU64x32 ((UINT64)CSize, CSizeMul), ReadBlLen);
    597       } else {
    598         Slot->SectorAddressing = TRUE;
    599         Csd2     = (SD_CSD2*)(VOID*)Csd;
    600         CSize    = (Csd2->CSizeHigh << 16 | Csd2->CSizeLow) + 1;
    601         Capacity = MultU64x32 ((UINT64)CSize, SIZE_512KB);
    602       }
    603 
    604       Slot->Media.LastBlock = DivU64x32 (Capacity, Slot->Media.BlockSize) - 1;
    605 
    606       Private->TotalBlkIoDevices++;
    607       Private->SlotNum++;
    608     }
    609 
    610     Controller++;
    611     if (!EFI_ERROR (Status)) {
    612       PeiServicesInstallPpi (&Private->BlkIoPpiList);
    613     }
    614   }
    615 
    616   return EFI_SUCCESS;
    617 }
    618