Home | History | Annotate | Download | only in FlashDeviceLib
      1 /** @file
      2 
      3   Copyright (c) 2004  - 2016, Intel Corporation. All rights reserved.<BR>
      4 
      5   This program and the accompanying materials are licensed and made available under
      6   the terms and conditions of the BSD License that accompanies this distribution.
      7   The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php.
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 
     14 
     15 **/
     16 
     17 #include <PiDxe.h>
     18 
     19 #include <Library/FlashDeviceLib.h>
     20 #include <Library/DebugLib.h>
     21 #include <Library/BaseLib.h>
     22 #include <Library/BaseMemoryLib.h>
     23 #include <Guid/EventGroup.h>
     24 #include <Library/SpiFlash.H>
     25 
     26 #define FLASH_SIZE  0x400000
     27 
     28 #define FLASH_DEVICE_BASE_ADDRESS (0xFFFFFFFF-FLASH_SIZE+1)
     29 UINTN FlashDeviceBase = FLASH_DEVICE_BASE_ADDRESS;
     30 
     31 EFI_SPI_PROTOCOL *mSpiProtocol = NULL;
     32 
     33 EFI_STATUS
     34 SpiFlashErase (
     35   UINT8 *BaseAddress,
     36   UINTN NumBytes
     37   )
     38 {
     39   EFI_STATUS          Status = EFI_SUCCESS;
     40   UINT32              SectorSize;
     41   UINT32              SpiAddress;
     42 
     43   SpiAddress = (UINT32)(UINTN)(BaseAddress) - (UINT32)FlashDeviceBase;
     44   SectorSize = SECTOR_SIZE_4KB;
     45   while ( (NumBytes > 0) && (NumBytes <= MAX_FWH_SIZE) ) {
     46     Status = mSpiProtocol->Execute (
     47                              mSpiProtocol,
     48                              SPI_SERASE,
     49                              SPI_WREN,
     50                              FALSE,
     51                              TRUE,
     52                              FALSE,
     53                              (UINT32) SpiAddress,
     54                              0,
     55                              NULL,
     56                              EnumSpiRegionBios
     57                              );
     58     if (EFI_ERROR (Status)) {
     59       break;
     60     }
     61     SpiAddress += SectorSize;
     62     NumBytes   -= SectorSize;
     63   }
     64 
     65   return Status;
     66 }
     67 
     68 
     69 EFI_STATUS
     70 SpiFlashBlockErase (
     71   UINT8 *BaseAddress,
     72   UINTN NumBytes
     73   )
     74 {
     75   EFI_STATUS          Status = EFI_SUCCESS;
     76   UINT32              SectorSize;
     77   UINT32              SpiAddress;
     78 
     79   SpiAddress = (UINT32)(UINTN)(BaseAddress) - (UINT32)FlashDeviceBase;
     80   SectorSize = SECTOR_SIZE_64KB;
     81   while ( (NumBytes > 0) && (NumBytes <= MAX_FWH_SIZE) ) {
     82     Status = mSpiProtocol->Execute (
     83                              mSpiProtocol,
     84                              SPI_BERASE,
     85                              SPI_WREN,
     86                              FALSE,
     87                              TRUE,
     88                              FALSE,
     89                              (UINT32) SpiAddress,
     90                              0,
     91                              NULL,
     92                              EnumSpiRegionBios
     93                              );
     94     if (EFI_ERROR (Status)) {
     95       break;
     96     }
     97     SpiAddress += SectorSize;
     98     NumBytes   -= SectorSize;
     99   }
    100 
    101   return Status;
    102 }
    103 
    104 
    105 static
    106 EFI_STATUS
    107 SpiFlashWrite (
    108   UINT8 *DstBufferPtr,
    109   UINT8 *Byte,
    110   IN  UINTN Length
    111   )
    112 {
    113   EFI_STATUS                Status;
    114   UINT32                    NumBytes = (UINT32)Length;
    115   UINT8*                    pBuf8 = Byte;
    116   UINT32                    SpiAddress;
    117 
    118   SpiAddress = (UINT32)(UINTN)(DstBufferPtr) - (UINT32)FlashDeviceBase;
    119   Status = mSpiProtocol->Execute (
    120                            mSpiProtocol,
    121                            SPI_PROG,
    122                            SPI_WREN,
    123                            TRUE,
    124                            TRUE,
    125                            TRUE,
    126                            (UINT32)SpiAddress,
    127                            NumBytes,
    128                            pBuf8,
    129                            EnumSpiRegionBios
    130                            );
    131   return Status;
    132 }
    133 
    134 /**
    135   Read the Serial Flash Status Registers.
    136 
    137   @param  SpiStatus         Pointer to a caller-allocated UINT8. On successful return, it contains the
    138                             status data read from the Serial Flash Status Register.
    139 
    140 
    141   @retval EFI_SUCCESS       Operation success, status is returned in SpiStatus.
    142   @retval EFI_DEVICE_ERROR  The block device is not functioning correctly and the operation failed.
    143 
    144 **/
    145 EFI_STATUS
    146 ReadStatusRegister (
    147   UINT8   *SpiStatus
    148   )
    149 {
    150   EFI_STATUS          Status;
    151 
    152   Status = mSpiProtocol->Execute (
    153              mSpiProtocol,
    154              SPI_RDSR,
    155              SPI_WREN,
    156              TRUE,
    157              FALSE,
    158              FALSE,
    159              0,
    160              1,
    161              SpiStatus,
    162              EnumSpiRegionBios
    163              );
    164   return Status;
    165 }
    166 
    167 EFI_STATUS
    168 SpiFlashLock (
    169     IN  UINT8  *BaseAddress,
    170     IN  UINTN  NumBytes,
    171     IN  BOOLEAN  Lock
    172   )
    173 {
    174   EFI_STATUS          Status;
    175   UINT8               SpiData;
    176   UINT8               SpiStatus;
    177 
    178   if (Lock) {
    179     SpiData = SF_SR_WPE;
    180   } else {
    181     SpiData = 0;
    182   }
    183 
    184   //
    185   // Always disable block protection to workaround tool issue.
    186   // Feature may be re-enabled in a future bios.
    187   //
    188   SpiData = 0;
    189   Status = mSpiProtocol->Execute (
    190                            mSpiProtocol,
    191                            SPI_WRSR,
    192                            SPI_EWSR,
    193                            TRUE,
    194                            TRUE,
    195                            TRUE,
    196                            0,
    197                            1,
    198                            &SpiData,
    199                            EnumSpiRegionBios
    200                            );
    201   if (EFI_ERROR (Status)) {
    202     return Status;
    203   }
    204 
    205   Status = ReadStatusRegister (&SpiStatus);
    206   if (EFI_ERROR (Status)) {
    207     return Status;
    208   }
    209 
    210   if ((SpiStatus & SpiData) != SpiData) {
    211     Status = EFI_DEVICE_ERROR;
    212   }
    213 
    214   return Status;
    215 }
    216 
    217 
    218 /**
    219   Read NumBytes bytes of data from the address specified by
    220   PAddress into Buffer.
    221 
    222   @param[in]      PAddress          The starting physical address of the read.
    223   @param[in,out]  NumBytes          On input, the number of bytes to read. On output, the number
    224                                     of bytes actually read.
    225   @param[out]     Buffer            The destination data buffer for the read.
    226 
    227   @retval         EFI_SUCCESS.      Opertion is successful.
    228   @retval         EFI_DEVICE_ERROR  If there is any device errors.
    229 
    230 **/
    231 EFI_STATUS
    232 EFIAPI
    233 LibFvbFlashDeviceRead (
    234   IN      UINTN                           PAddress,
    235   IN  OUT UINTN                           *NumBytes,
    236       OUT UINT8                           *Buffer
    237   )
    238 {
    239   CopyMem(Buffer, (VOID*)PAddress, *NumBytes);
    240   return EFI_SUCCESS;
    241 }
    242 
    243 
    244 /**
    245   Write NumBytes bytes of data from Buffer to the address specified by
    246   PAddresss.
    247 
    248   @param[in]      PAddress          The starting physical address of the write.
    249   @param[in,out]  NumBytes          On input, the number of bytes to write. On output,
    250                                     the actual number of bytes written.
    251   @param[in]      Buffer            The source data buffer for the write.
    252 
    253   @retval         EFI_SUCCESS.      Opertion is successful.
    254   @retval         EFI_DEVICE_ERROR  If there is any device errors.
    255 
    256 **/
    257 EFI_STATUS
    258 EFIAPI
    259 LibFvbFlashDeviceWrite (
    260   IN        UINTN                           PAddress,
    261   IN OUT    UINTN                           *NumBytes,
    262   IN        UINT8                           *Buffer
    263   )
    264 {
    265 EFI_STATUS Status;
    266   Status =  SpiFlashWrite((UINT8 *)PAddress, Buffer, *NumBytes);
    267  return Status;
    268 }
    269 
    270 
    271 /**
    272   Erase the block staring at PAddress.
    273 
    274   @param[in]  PAddress          The starting physical address of the block to be erased.
    275                                 This library assume that caller garantee that the PAddress
    276                                 is at the starting address of this block.
    277   @param[in]  LbaLength         The length of the logical block to be erased.
    278 
    279   @retval     EFI_SUCCESS.      Opertion is successful.
    280   @retval     EFI_DEVICE_ERROR  If there is any device errors.
    281 
    282 **/
    283 EFI_STATUS
    284 EFIAPI
    285 LibFvbFlashDeviceBlockErase (
    286   IN    UINTN                     PAddress,
    287   IN    UINTN                     LbaLength
    288   )
    289 {
    290   EFI_STATUS Status;
    291   Status = SpiFlashBlockErase((UINT8 *)PAddress, LbaLength);
    292 
    293   return Status;
    294 }
    295 
    296 
    297 /**
    298   Lock or unlock the block staring at PAddress.
    299 
    300   @param[in]  PAddress        The starting physical address of region to be (un)locked.
    301   @param[in]  LbaLength       The length of the logical block to be erased.
    302   @param[in]  Lock            TRUE to lock. FALSE to unlock.
    303 
    304   @retval     EFI_SUCCESS.      Opertion is successful.
    305   @retval     EFI_DEVICE_ERROR  If there is any device errors.
    306 
    307 **/
    308 EFI_STATUS
    309 EFIAPI
    310 LibFvbFlashDeviceBlockLock (
    311   IN    UINTN                          PAddress,
    312   IN    UINTN                          LbaLength,
    313   IN    BOOLEAN                        Lock
    314   )
    315 {
    316   EFI_STATUS Status;
    317 
    318     Status = SpiFlashLock((UINT8*)PAddress, LbaLength, Lock);
    319   return Status;
    320 }
    321 
    322