Home | History | Annotate | Download | only in NorFlashDxe
      1 /** @file
      2 *
      3 *  Copyright (c) 2015, Hisilicon Limited. All rights reserved.
      4 *  Copyright (c) 2015, Linaro Limited. All rights reserved.
      5 *
      6 *  This program and the accompanying materials
      7 *  are licensed and made available under the terms and conditions of the BSD License
      8 *  which accompanies this distribution.  The full text of the license may be found at
      9 *  http://opensource.org/licenses/bsd-license.php
     10 *
     11 *  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 *  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 *
     14 **/
     15 
     16 #include <PiDxe.h>
     17 #include <Library/DebugLib.h>
     18 #include <Library/UefiBootServicesTableLib.h>
     19 #include <Library/IoLib.h>
     20 #include "NorFlashHw.h"
     21 
     22 
     23 BOOLEAN  gFlashBusy = FALSE;
     24 FLASH_INDEX gIndex = {
     25     0,
     26     0,
     27     0,
     28     0,
     29     0,
     30     0
     31 };
     32 
     33 
     34 UINT32 PortReadData (
     35     UINT32 Index,
     36     UINT32 FlashAddr
     37   )
     38 {
     39 
     40     switch (gFlashInfo[Index].ParallelNum)
     41     {
     42         case 2:
     43             return MmioRead32 (FlashAddr);
     44         case 1:
     45             return MmioRead16 (FlashAddr);
     46 
     47         default:
     48             DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:illegal PortWidth!\n", __FUNCTION__,__LINE__));
     49             return 0xffffffff;
     50     }
     51 }
     52 
     53 EFI_STATUS
     54 PortWriteData (
     55     UINT32 Index,
     56     UINT32 FlashAddr,
     57     UINT32 InputData
     58   )
     59 {
     60 
     61     switch (gFlashInfo[Index].ParallelNum)
     62     {
     63         case 2:
     64              MmioWrite32 (FlashAddr, InputData);
     65              break;
     66         case 1:
     67              MmioWrite16 (FlashAddr, InputData);
     68              break;
     69         default:
     70              DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:illegal PortWidth!\n", __FUNCTION__,__LINE__));
     71              return EFI_DEVICE_ERROR;
     72     }
     73     return EFI_SUCCESS;
     74 }
     75 
     76 UINT32 PortAdjustData(
     77     UINT32 Index,
     78     UINT32 ulInputData
     79   )
     80 {
     81 
     82     switch (gFlashInfo[Index].ParallelNum)
     83     {
     84         case 2:
     85              return ulInputData;
     86         case 1:
     87              return (0x0000ffff & ulInputData );
     88         default:
     89             DEBUG((EFI_D_ERROR,"[FLASH_S29GL256N_PortAdjustData]: Error--illegal g_ulFlashS29Gl256NPortWidth!\n\r"));
     90             return 0xffffffff;
     91     }
     92 }
     93 
     94 
     95 EFI_STATUS GetCommandIndex(
     96     UINT32 Index
     97   )
     98 {
     99     UINT32 CommandCount = 0;
    100     UINT32 i;
    101     UINT8 Flag = 1;
    102 
    103     CommandCount = sizeof(gFlashCommandReset) / sizeof(FLASH_COMMAND_RESET);
    104     for(i = 0;i < CommandCount; i ++ )
    105     {
    106         if(gFlashInfo[Index].CommandType & gFlashCommandReset[i].CommandType)
    107         {
    108             Flag = 0;
    109             gIndex.ReIndex = i;
    110             break;
    111         }
    112     }
    113 
    114     if(Flag)
    115     {
    116         DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Can not Get Reset Command!\n", __FUNCTION__,__LINE__));
    117         return EFI_DEVICE_ERROR;
    118     }
    119 
    120     CommandCount = sizeof(gFlashCommandId) / sizeof(FLASH_COMMAND_ID);
    121     for(Flag = 1,i = 0;i < CommandCount; i ++ )
    122     {
    123         if(gFlashInfo[Index].CommandType & gFlashCommandId[i].CommandType)
    124         {
    125             Flag = 0;
    126             gIndex.IdIndex = i;
    127             break;
    128         }
    129     }
    130 
    131     if(Flag)
    132     {
    133         DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Can not Get ID Command!\n", __FUNCTION__,__LINE__));
    134         return EFI_DEVICE_ERROR;
    135     }
    136 
    137     CommandCount = sizeof(gFlashCommandWrite) / sizeof(FLASH_COMMAND_WRITE);
    138     for(Flag = 1, i = 0;i < CommandCount; i ++ )
    139     {
    140         if(gFlashInfo[Index].CommandType & gFlashCommandWrite[i].CommandType)
    141         {
    142             Flag = 0;
    143             gIndex.WIndex = i;
    144             break;
    145         }
    146     }
    147 
    148     if(Flag)
    149     {
    150         DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Can not Get Write Command!\n", __FUNCTION__,__LINE__));
    151         return EFI_DEVICE_ERROR;
    152     }
    153 
    154     CommandCount = sizeof(gFlashCommandErase) / sizeof(FLASH_COMMAND_ERASE);
    155     for(Flag = 1, i = 0;i < CommandCount; i ++ )
    156     {
    157         if(gFlashInfo[Index].CommandType & gFlashCommandErase[i].CommandType)
    158         {
    159             Flag = 0;
    160             gIndex.WIndex = i;
    161             break;
    162         }
    163     }
    164 
    165     if(Flag)
    166     {
    167         DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Can not Get Erase Command!\n", __FUNCTION__,__LINE__));
    168         return EFI_DEVICE_ERROR;
    169     }
    170 
    171     return EFI_SUCCESS;
    172 }
    173 
    174 
    175 VOID FlashReset(UINT32 Base)
    176 {
    177     (VOID)PortWriteData(gIndex.InfIndex, Base, gFlashCommandReset[gIndex.ReIndex].ResetData);
    178     (void)gBS->Stall(20000);
    179 }
    180 
    181 
    182 void GetManufacturerID(UINT32 Index, UINT32 Base, UINT8 *pbyData)
    183 {
    184 
    185     UINT32 dwAddr;
    186 
    187     FlashReset(Base);
    188 
    189     dwAddr = Base +  (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep1 << gFlashInfo[Index].ParallelNum);
    190     (VOID)PortWriteData(Index, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep1);
    191 
    192     dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep2 << gFlashInfo[Index].ParallelNum);
    193     (VOID)PortWriteData(Index, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep2);
    194 
    195     dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep3 << gFlashInfo[Index].ParallelNum);
    196     (VOID)PortWriteData(Index, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep3);
    197 
    198     *pbyData = (UINT8)PortReadData(Index, Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddress << gFlashInfo[Index].ParallelNum));
    199 
    200     FlashReset(Base);    //must reset to return to the read mode
    201 }
    202 
    203 
    204 EFI_STATUS FlashInit(UINT32 Base)
    205 {
    206     UINT32 FlashCount = 0;
    207     UINT32 i = 0;
    208     EFI_STATUS Status;
    209     UINT8 Flag = 1;
    210     UINT32 TempData = 0;
    211     UINT32 TempDev1 = 0;
    212     UINT32 TempDev2 = 0;
    213     UINT32 TempDev3 = 0;
    214     UINT32 dwAddr;
    215 
    216     FlashCount = sizeof(gFlashInfo) / sizeof(NOR_FLASH_INFO_TABLE);
    217     for(;i < FlashCount; i ++ )
    218     {
    219 
    220         Status = GetCommandIndex(i);
    221         if (EFI_ERROR(Status))
    222          {
    223              DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Get Command Index %r!\n", __FUNCTION__,__LINE__, Status));
    224              return Status;
    225          }
    226 
    227         FlashReset(Base);
    228 
    229         dwAddr = Base +  (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep1 << gFlashInfo[i].ParallelNum);
    230         (VOID)PortWriteData(i, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep1);
    231 
    232         dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep2 << gFlashInfo[i].ParallelNum);
    233         (VOID)PortWriteData(i, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep2);
    234 
    235         dwAddr = Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddressStep3 << gFlashInfo[i].ParallelNum);
    236         (VOID)PortWriteData(i, dwAddr, gFlashCommandId[gIndex.IdIndex].ManuIDDataStep3);
    237         //Get manufacture ID
    238         TempData = PortReadData(i, Base + (gFlashCommandId[gIndex.IdIndex].ManuIDAddress << gFlashInfo[i].ParallelNum));
    239 
    240         //Get Device Id
    241         TempDev1 = PortReadData(i, Base + (gFlashCommandId[gIndex.IdIndex].DeviceIDAddress1 << gFlashInfo[i].ParallelNum));
    242         TempDev2 = PortReadData(i, Base + (gFlashCommandId[gIndex.IdIndex].DeviceIDAddress2 << gFlashInfo[i].ParallelNum));
    243         TempDev3 = PortReadData(i, Base + (gFlashCommandId[gIndex.IdIndex].DeviceIDAddress3 << gFlashInfo[i].ParallelNum));
    244         DEBUG ((EFI_D_ERROR, "[cdtest]manufactor ID 0x%x!\n",TempData));
    245         DEBUG ((EFI_D_ERROR, "[cdtest]Device ID 1 0x%x!\n",TempDev1));
    246         DEBUG ((EFI_D_ERROR, "[cdtest]Device ID 2 0x%x!\n",TempDev2));
    247         DEBUG ((EFI_D_ERROR, "[cdtest]Device ID 3 0x%x!\n",TempDev3));
    248 
    249         FlashReset(Base);
    250 
    251 
    252         if((0xffffffff != TempData)
    253             && (PortAdjustData(i, gFlashInfo[i].ManufacturerID) == TempData))
    254         {
    255             if((0xffffffff != TempDev1)
    256                 && (PortAdjustData(i, gFlashInfo[i].DeviceID1) == TempDev1))
    257             {
    258                 if((0xffffffff != TempDev2)
    259                     && (PortAdjustData(i, gFlashInfo[i].DeviceID2) == TempDev2))
    260                 {
    261                     if((0xffffffff != TempDev3)
    262                         && (PortAdjustData(i, gFlashInfo[i].DeviceID3) == TempDev3))
    263                     {
    264                         Flag = 0;
    265                         gIndex.InfIndex = i;
    266                         break;
    267                     }
    268                 }
    269             }
    270          }
    271     }
    272 
    273     if(Flag)
    274     {
    275         return EFI_DEVICE_ERROR;
    276     }
    277 
    278     return EFI_SUCCESS;
    279 }
    280 
    281 
    282 static BOOLEAN width8IsAll(
    283     const UINT64       Base,
    284     const UINT64       Offset,
    285     const UINT64       Length,
    286     const UINT8        Value
    287 )
    288 {
    289     UINT64 NewAddr = Base + Offset;
    290     UINT64 NewLength = Length;
    291     while (NewLength --)
    292     {
    293         if (*(UINT8 *)(UINTN)NewAddr == Value)
    294         {
    295             NewAddr ++;
    296             continue;
    297         }
    298         else
    299         {
    300             return FALSE;
    301         }
    302     }
    303     return TRUE;
    304 }
    305 
    306 
    307 
    308 EFI_STATUS BufferWriteCommand(UINTN Base, UINTN Offset, void *pData)
    309 {
    310     UINT32 dwCommAddr;
    311     UINT32 *pdwData;
    312     UINT16 *pwData;
    313     UINT32 dwLoop;
    314     UINT32 ulWriteWordCount;
    315     UINT32 dwAddr;
    316 
    317     if(gFlashBusy)
    318     {
    319         DEBUG((EFI_D_ERROR, "[%a]:[%dL]:Flash is busy!\n", __FUNCTION__,__LINE__));
    320         return EFI_NOT_READY;
    321     }
    322     gFlashBusy = TRUE;
    323 
    324     if(2 == gFlashInfo[gIndex.InfIndex].ParallelNum)
    325     {
    326         pdwData = (UINT32 *)pData;
    327 
    328         dwAddr = (UINT32)Base + (gFlashCommandWrite[gIndex.WIndex].BufferProgramAddressStep1 << gFlashInfo[gIndex.InfIndex].ParallelNum);
    329         (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep1);
    330 
    331         dwAddr = (UINT32)Base + (gFlashCommandWrite[gIndex.WIndex].BufferProgramAddressStep2 << gFlashInfo[gIndex.InfIndex].ParallelNum);
    332         (VOID)PortWriteData(gIndex.InfIndex, dwAddr,  gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep2);
    333 
    334         //dwAddr = Base + (Offset << gFlashInfo[gIndex.InfIndex].ParallelNum);
    335         dwAddr = (UINT32)Base + Offset;
    336         (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep3);
    337 
    338 
    339        ulWriteWordCount = ((gFlashInfo[gIndex.InfIndex].BufferProgramSize - 1) << 16) | (gFlashInfo[gIndex.InfIndex].BufferProgramSize - 1);
    340        (VOID)PortWriteData(gIndex.InfIndex, dwAddr, ulWriteWordCount);
    341 
    342 
    343        for (dwLoop = 0; dwLoop < gFlashInfo[gIndex.InfIndex].BufferProgramSize; dwLoop ++)
    344        {
    345            dwCommAddr = (UINT32)Base + (UINT32)Offset + (dwLoop << gFlashInfo[gIndex.InfIndex].ParallelNum);
    346            MmioWrite32 (dwCommAddr, *pdwData);
    347            pdwData ++;
    348        }
    349 
    350        dwAddr = (UINT32)Base + (UINT32)Offset + ((gFlashInfo[gIndex.InfIndex].BufferProgramSize - 1) << gFlashInfo[gIndex.InfIndex].ParallelNum);
    351        (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramtoFlash);
    352 
    353 
    354 
    355     }
    356     else
    357     {
    358         pwData  = (UINT16 *)pData;
    359 
    360         dwAddr = (UINT32)Base + (gFlashCommandWrite[gIndex.WIndex].BufferProgramAddressStep1 << gFlashInfo[gIndex.InfIndex].ParallelNum);
    361         (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep1);
    362 
    363         dwAddr = (UINT32)Base + (gFlashCommandWrite[gIndex.WIndex].BufferProgramAddressStep2 << gFlashInfo[gIndex.InfIndex].ParallelNum);
    364         (VOID)PortWriteData(gIndex.InfIndex, dwAddr,  gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep2);
    365 
    366         //dwAddr = Base + (Offset << gFlashInfo[gIndex.InfIndex].ParallelNum);
    367         dwAddr = (UINT32)Base + Offset;
    368         (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramDataStep3);
    369 
    370 
    371         ulWriteWordCount = gFlashInfo[gIndex.InfIndex].BufferProgramSize - 1;
    372         (VOID)PortWriteData(gIndex.InfIndex, dwAddr, ulWriteWordCount);
    373 
    374 
    375         for (dwLoop = 0; dwLoop < gFlashInfo[gIndex.InfIndex].BufferProgramSize; dwLoop ++)
    376         {
    377             dwCommAddr = (UINT32)Base + (UINT32)Offset + (dwLoop << gFlashInfo[gIndex.InfIndex].ParallelNum);
    378             MmioWrite16 (dwCommAddr, *pwData);
    379             pwData ++;
    380         }
    381 
    382         dwAddr = (UINT32)Base + (UINT32)Offset + ((gFlashInfo[gIndex.InfIndex].BufferProgramSize - 1) << gFlashInfo[gIndex.InfIndex].ParallelNum);
    383         (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandWrite[gIndex.WIndex].BufferProgramtoFlash);
    384 
    385     }
    386 
    387     (void)gBS->Stall(200);
    388 
    389     gFlashBusy = FALSE;
    390     return EFI_SUCCESS;
    391 
    392 }
    393 
    394 
    395 EFI_STATUS SectorEraseCommand(UINTN Base, UINTN Offset)
    396 {
    397     UINT32 dwAddr;
    398 
    399     if(gFlashBusy)
    400     {
    401         DEBUG((EFI_D_ERROR, "[%a]:[%dL]:Flash is busy!\n", __FUNCTION__,__LINE__));
    402         return EFI_NOT_READY;
    403     }
    404 
    405     gFlashBusy = TRUE;
    406 
    407     dwAddr = (UINT32)Base + (gFlashCommandErase[gIndex.EIndex].SectorEraseAddressStep1 << gFlashInfo[gIndex.InfIndex].ParallelNum);
    408     (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep1);
    409 
    410     dwAddr = (UINT32)Base + (gFlashCommandErase[gIndex.EIndex].SectorEraseAddressStep2 << gFlashInfo[gIndex.InfIndex].ParallelNum);
    411     (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep2);
    412 
    413     dwAddr = (UINT32)Base + (gFlashCommandErase[gIndex.EIndex].SectorEraseAddressStep3 << gFlashInfo[gIndex.InfIndex].ParallelNum);
    414     (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep3);
    415 
    416     dwAddr = (UINT32)Base + (gFlashCommandErase[gIndex.EIndex].SectorEraseAddressStep4 << gFlashInfo[gIndex.InfIndex].ParallelNum);
    417     (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep4);
    418 
    419     dwAddr = (UINT32)Base + (gFlashCommandErase[gIndex.EIndex].SectorEraseAddressStep5 << gFlashInfo[gIndex.InfIndex].ParallelNum);
    420     (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep5);
    421 
    422     dwAddr = (UINT32)Base + Offset;
    423     (VOID)PortWriteData(gIndex.InfIndex, dwAddr, gFlashCommandErase[gIndex.EIndex].SectorEraseDataStep6);
    424 
    425     (void)gBS->Stall(500000);
    426 
    427     gFlashBusy = FALSE;
    428     return EFI_SUCCESS;
    429 }
    430 
    431 
    432 EFI_STATUS CompleteCheck(UINT32 Base, UINT32 Offset, void *pData, UINT32 Length)
    433 {
    434     UINT32 dwTestAddr;
    435     UINT32 dwTestData;
    436     UINT32 dwTemp = 0;
    437     UINT32 dwTemp1 = 0;
    438     UINT32 i;
    439     UINT32 dwTimeOut = 3000000;
    440 
    441     if(gFlashBusy)
    442     {
    443         DEBUG((EFI_D_ERROR, "[%a]:[%dL]:Flash is busy!\n", __FUNCTION__,__LINE__));
    444         return EFI_NOT_READY;
    445     }
    446     gFlashBusy = TRUE;
    447 
    448     if(2 == gFlashInfo[gIndex.InfIndex].ParallelNum)
    449     {
    450         dwTestAddr = Base + Offset + Length - sizeof(UINT32);
    451         dwTestData = *((UINT32 *)((UINT8 *)pData + Length - sizeof(UINT32)));
    452 
    453         while(dwTimeOut--)
    454         {
    455             dwTemp1 = MmioRead32 (dwTestAddr);
    456             if (dwTestData == dwTemp1)
    457             {
    458                 dwTemp = MmioRead32 (dwTestAddr);
    459                 dwTemp1 = MmioRead32 (dwTestAddr);
    460                 if ((dwTemp == dwTemp1) && (dwTestData == dwTemp1))
    461                 {
    462                     gFlashBusy = FALSE;
    463                     return EFI_SUCCESS;
    464                 }
    465             }
    466 
    467             (void)gBS->Stall(1);
    468         }
    469 
    470         if((UINT16)(dwTemp1 >> 16) != (UINT16)(dwTestData >> 16))
    471         {
    472             DEBUG((EFI_D_ERROR, "CompleteCheck ERROR: chip1 address %x, buffer %x, flash %x!\n", Offset, dwTestData, dwTemp1));
    473         }
    474         if((UINT16)(dwTemp1) != (UINT16)(dwTestData))
    475         {
    476             DEBUG((EFI_D_ERROR, "CompleteCheck ERROR: chip2 address %x, buffer %x, flash %x!\n", Offset, dwTestData, dwTemp1));
    477         }
    478     }
    479     else
    480     {
    481         dwTestAddr = Base + Offset + Length - sizeof(UINT16);
    482         dwTestData = *((UINT16 *)((UINT8 *)pData + Length - sizeof(UINT16)));
    483 
    484         while(dwTimeOut--)
    485         {
    486             dwTemp1 = MmioRead16 (dwTestAddr);
    487             if (dwTestData == dwTemp1)
    488             {
    489                 dwTemp = MmioRead16 (dwTestAddr);
    490                 dwTemp1 = MmioRead16 (dwTestAddr);
    491                 if ((dwTemp == dwTemp1) && (dwTestData == dwTemp1))
    492                 {
    493                     gFlashBusy = FALSE;
    494                     return EFI_SUCCESS;
    495                 }
    496             }
    497 
    498             (void)gBS->Stall(1);
    499         }
    500     }
    501 
    502     for(i = 0; i < 5; i ++)
    503     {
    504         DEBUG((EFI_D_ERROR, "CompleteCheck ERROR: flash %x\n",PortReadData(gIndex.InfIndex, dwTestAddr)));
    505     }
    506 
    507     FlashReset(Base);
    508 
    509     gFlashBusy = FALSE;
    510     DEBUG((EFI_D_ERROR, "CompleteCheck ERROR: timeout address %x, buffer %x, flash %x\n", Offset, dwTestData, dwTemp1));
    511     return EFI_TIMEOUT;
    512 }
    513 
    514 EFI_STATUS IsNeedToWrite(
    515     IN  UINT32         Base,
    516     IN  UINT32       Offset,
    517     IN  UINT8       *Buffer,
    518     IN  UINT32       Length
    519   )
    520 {
    521     UINTN NewAddr = Base + Offset;
    522     UINT8 FlashData = 0;
    523     UINT8 BufferData = 0;
    524 
    525     for(; Length > 0; Length --)
    526     {
    527         BufferData = *Buffer;
    528         //lint -epn -e511
    529         FlashData = *(UINT8 *)NewAddr;
    530         if (BufferData != FlashData)
    531         {
    532             return TRUE;
    533         }
    534         NewAddr ++;
    535         Buffer ++;
    536     }
    537 
    538     return FALSE;
    539 }
    540 
    541 
    542 EFI_STATUS BufferWrite(UINT32 Offset, void *pData, UINT32 Length)
    543 {
    544     EFI_STATUS Status;
    545     UINT32 dwLoop;
    546     UINT32 Retry = 3;
    547 
    548     if (FALSE == IsNeedToWrite(gIndex.Base, Offset, (UINT8 *)pData, Length))
    549     {
    550         return EFI_SUCCESS;
    551     }
    552 
    553     do
    554     {
    555         (void)BufferWriteCommand(gIndex.Base, Offset, pData);
    556         Status = CompleteCheck(gIndex.Base, Offset, pData, Length);
    557 
    558 
    559         if (EFI_SUCCESS == Status)
    560         {
    561             for (dwLoop = 0; dwLoop < Length; dwLoop ++)
    562             {
    563                 if (*(UINT8 *)(UINTN)(gIndex.Base + Offset + dwLoop) != *((UINT8 *)pData + dwLoop))
    564                 {
    565                     DEBUG((EFI_D_ERROR, "Flash_WriteUnit ERROR: address %x, buffer %x, flash %x\n", Offset, *((UINT8 *)pData + dwLoop), *(UINT8 *)(UINTN)(gIndex.Base + Offset + dwLoop)));
    566                     Status = EFI_ABORTED;
    567                     continue;
    568                 }
    569             }
    570         }
    571         else
    572         {
    573             DEBUG((EFI_D_ERROR, "Flash_WriteUnit ERROR: complete check failed, %r\n", Status));
    574             continue;
    575         }
    576     } while ((Retry--) && EFI_ERROR(Status));
    577 
    578     return Status;
    579 }
    580 
    581 
    582 EFI_STATUS SectorErase(UINT32 Base, UINT32 Offset)
    583 {
    584     UINT8 gTemp[FLASH_MAX_UNIT];
    585     UINT64 dwLoop = FLASH_MAX_UNIT - 1;
    586     UINT32 Retry = 3;
    587     EFI_STATUS Status;
    588 
    589     do
    590     {
    591         gTemp[dwLoop] = 0xFF;
    592     }while (dwLoop --);
    593 
    594     do
    595     {
    596         (void)SectorEraseCommand(Base, Offset);
    597         Status = CompleteCheck(Base, Offset, (void *)gTemp, FLASH_MAX_UNIT);
    598 
    599 
    600         if (EFI_SUCCESS == Status)
    601         {
    602 
    603             if (width8IsAll(Base,Offset - (Offset % gFlashInfo[gIndex.InfIndex].BlockSize), gFlashInfo[gIndex.InfIndex].BlockSize, 0xFF))
    604             {
    605                 return EFI_SUCCESS;
    606             }
    607             else
    608             {
    609                 DEBUG((EFI_D_ERROR, "Flash_SectorErase ERROR: not all address equal 0xFF\n"));
    610 
    611                 Status = EFI_ABORTED;
    612                 continue;
    613             }
    614         }
    615         else
    616         {
    617             DEBUG((EFI_D_ERROR, "Flash_SectorErase ERROR: complete check failed, %r\n", Status));
    618             continue;
    619         }
    620     }while ((Retry--) && EFI_ERROR(Status));
    621 
    622     if(Retry)
    623     {
    624         //do nothing for pclint
    625     }
    626 
    627     return Status;
    628 }
    629