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