• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PortReadData(UINT32 Index,UINT32 FlashAddr)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
PortWriteData(UINT32 Index,UINT32 FlashAddr,UINT32 InputData)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 
PortAdjustData(UINT32 Index,UINT32 ulInputData)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 
GetCommandIndex(UINT32 Index)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 
FlashReset(UINT32 Base)175 VOID FlashReset(UINT32 Base)
176 {
177     (VOID)PortWriteData(gIndex.InfIndex, Base, gFlashCommandReset[gIndex.ReIndex].ResetData);
178     (void)gBS->Stall(20000);
179 }
180 
181 
GetManufacturerID(UINT32 Index,UINT32 Base,UINT8 * pbyData)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 
FlashInit(UINT32 Base)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 
width8IsAll(const UINT64 Base,const UINT64 Offset,const UINT64 Length,const UINT8 Value)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 
BufferWriteCommand(UINTN Base,UINTN Offset,void * pData)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 
SectorEraseCommand(UINTN Base,UINTN Offset)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 
CompleteCheck(UINT32 Base,UINT32 Offset,void * pData,UINT32 Length)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 
IsNeedToWrite(IN UINT32 Base,IN UINT32 Offset,IN UINT8 * Buffer,IN UINT32 Length)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 
BufferWrite(UINT32 Offset,void * pData,UINT32 Length)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 
SectorErase(UINT32 Base,UINT32 Offset)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