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
17 #include <Uefi.h>
18 #include <Library/DebugLib.h>
19 #include <Library/UefiBootServicesTableLib.h>
20 #include <Library/ArmLib.h>
21 #include <Library/PcdLib.h>
22 #include <Protocol/NorFlashProtocol.h>
23 #include <Library/DxeServicesTableLib.h>
24 #include <Protocol/Cpu.h>
25 #include "NorFlashHw.h"
26
27
28 EFI_STATUS Erase(
29 IN UNI_NOR_FLASH_PROTOCOL *This,
30 IN UINT32 Offset,
31 IN UINT32 Length
32 );
33
34 EFI_STATUS Write(
35 IN UNI_NOR_FLASH_PROTOCOL *This,
36 IN UINT32 Offset,
37 IN UINT8 *Buffer,
38 UINT32 ulLength
39 );
40
41 EFI_STATUS Read(
42 IN UNI_NOR_FLASH_PROTOCOL *This,
43 IN UINT32 Offset,
44 IN OUT UINT8 *Buffer,
45 IN UINT32 ulLen
46 );
47
48 UNI_NOR_FLASH_PROTOCOL gUniNorFlash = {
49 Erase,
50 Write,
51 Read
52 };
53
54
55 EFI_STATUS
Read(IN UNI_NOR_FLASH_PROTOCOL * This,IN UINT32 Offset,IN OUT UINT8 * Buffer,IN UINT32 ulLen)56 EFIAPI Read(
57 IN UNI_NOR_FLASH_PROTOCOL *This,
58 IN UINT32 Offset,
59 IN OUT UINT8 *Buffer,
60 IN UINT32 ulLen
61 )
62 {
63 UINT32 index;
64 UINT64 ullAddr;
65 UINT32 ullCnt = 0;
66 UINT32 *puiBuffer32 = NULL;
67 UINT32 *puiDst32 = NULL;
68 UINT8 *pucBuffer8 = NULL;
69 UINT8 *pucDst8 = NULL;
70
71 if (Offset + ulLen > (gFlashInfo[gIndex.InfIndex].SingleChipSize * gFlashInfo[gIndex.InfIndex].ParallelNum))
72 {
73 DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Exceed the flash scope!\n", __FUNCTION__,__LINE__));
74 return EFI_INVALID_PARAMETER;
75 }
76 if (0 == ulLen)
77 {
78 DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Length is Zero!\n", __FUNCTION__,__LINE__));
79 return EFI_INVALID_PARAMETER;
80 }
81 if (NULL == Buffer)
82 {
83 DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Buffer is NULL!\n", __FUNCTION__,__LINE__));
84 return EFI_BAD_BUFFER_SIZE;
85 }
86
87
88 ullAddr = gIndex.Base + Offset;
89
90 pucBuffer8 = (UINT8 *)Buffer;
91 pucDst8 = (UINT8 *)((UINTN)ullAddr);
92
93
94 if (ulLen < FOUR_BYTE_UNIT)
95 {
96 for(index = 0; index< ulLen; index++)
97 {
98 *pucBuffer8++ = *pucDst8++;
99 }
100 }
101 else
102 {
103
104 ullCnt = Offset % FOUR_BYTE_UNIT;
105 ullCnt = FOUR_BYTE_UNIT - ullCnt;
106
107 for(index = 0; index < ullCnt; index++)
108 {
109 *pucBuffer8++ = *pucDst8++;
110 }
111
112 ulLen -= ullCnt;
113
114 puiBuffer32 = (UINT32 *)pucBuffer8;
115 puiDst32 = (UINT32 *)pucDst8;
116 ullCnt = ulLen / FOUR_BYTE_UNIT;
117
118 for(index = 0; index < ullCnt; index++)
119 {
120 *puiBuffer32++ = *puiDst32++;
121 }
122
123 ullCnt = ulLen % FOUR_BYTE_UNIT;
124 pucBuffer8 = (UINT8 *)puiBuffer32;
125 pucDst8 = (UINT8 *)puiDst32;
126
127 for(index = 0; index < ullCnt; index++)
128 {
129 *pucBuffer8++ = *pucDst8++;
130 }
131 }
132
133 return EFI_SUCCESS;
134 }
135
136
137
WriteAfterErase_Fill(IN const UINT32 Offset,IN const UINT8 * Buffer,IN const UINT32 Length)138 static EFI_STATUS WriteAfterErase_Fill(
139 IN const UINT32 Offset,
140 IN const UINT8 *Buffer,
141 IN const UINT32 Length
142 )
143 {
144 EFI_STATUS Status;
145 UINT32 Loop;
146 UINT32 DataOffset;
147 UINT32 NewOffset;
148 UINT8 *NewDataUnit;
149
150 UINT32 FlashUnitLength;
151
152 FlashUnitLength = gFlashInfo[gIndex.InfIndex].BufferProgramSize << gFlashInfo[gIndex.InfIndex].ParallelNum;
153
154 if (0 == Length)
155 {
156 return EFI_SUCCESS;
157 }
158 if ((Offset % FlashUnitLength + Length) > FlashUnitLength)
159 {
160 DEBUG ((EFI_D_INFO, "[%a]:[%dL]:Exceed the Flash Size!\n", __FUNCTION__,__LINE__));
161 return EFI_UNSUPPORTED;
162 }
163
164
165 Status = gBS->AllocatePool(EfiBootServicesData, FlashUnitLength, (VOID *)&NewDataUnit);
166 if (EFI_ERROR(Status))
167 {
168 DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Allocate Pool failed, %r!\n", __FUNCTION__,__LINE__, Status));
169 return Status;
170 }
171
172
173 NewOffset = Offset - (Offset % FlashUnitLength);
174
175 gBS->CopyMem((VOID *)NewDataUnit, (VOID *)(UINTN)(gIndex.Base + NewOffset), FlashUnitLength);
176
177 DataOffset = Offset % FlashUnitLength;
178 for (Loop = 0; Loop < Length; Loop ++)
179 {
180 NewDataUnit[(UINT32)(DataOffset + Loop)] = Buffer[Loop];
181 }
182
183 Status = BufferWrite(NewOffset, (void *)NewDataUnit, FlashUnitLength);
184 if (EFI_ERROR(Status))
185 {
186 DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:BufferWrite %r!\n", __FUNCTION__,__LINE__, Status));
187 return Status;
188 }
189
190 (void)gBS->FreePool((VOID *)NewDataUnit);
191 return Status;
192 }
193
194
WriteAfterErase_Final(IN UINT32 Offset,IN UINT8 * Buffer,IN UINT32 Length)195 static EFI_STATUS WriteAfterErase_Final(
196 IN UINT32 Offset,
197 IN UINT8 *Buffer,
198 IN UINT32 Length
199 )
200 {
201 EFI_STATUS Status;
202 UINT32 Loop;
203 UINT32 FlashUnitLength;
204
205 FlashUnitLength = gFlashInfo[gIndex.InfIndex].BufferProgramSize << gFlashInfo[gIndex.InfIndex].ParallelNum;
206
207 if (0 == Length)
208 {
209 return EFI_SUCCESS;
210 }
211
212 if (0 != (Offset % FlashUnitLength))
213 {
214 DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: Offset must be a multiple of 0x%x!\n", __FUNCTION__,__LINE__,FlashUnitLength));
215 return EFI_UNSUPPORTED;
216 }
217
218
219 Loop = Length / FlashUnitLength;
220 while (Loop --)
221 {
222 Status = BufferWrite(Offset, (void *)Buffer, FlashUnitLength);
223 if (EFI_ERROR(Status))
224 {
225 DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:BufferWrite Failed: %r!\n", __FUNCTION__,__LINE__, Status));
226 return EFI_DEVICE_ERROR;
227 }
228 Offset += FlashUnitLength;
229 Buffer += FlashUnitLength;
230 }
231
232
233 Length = Length % FlashUnitLength;
234 if (Length)
235 {
236 Status = WriteAfterErase_Fill(Offset, Buffer, Length);
237 if (EFI_ERROR(Status))
238 {
239 DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:WriteAfterErase_Fill failed,%r!\n", __FUNCTION__,__LINE__, Status));
240 return Status;
241 }
242 }
243
244 return EFI_SUCCESS;
245 }
246
247 EFI_STATUS
WriteAfterErase(UINT32 TempBase,UINT32 Offset,UINT8 * Buffer,UINT32 Length)248 WriteAfterErase(
249 UINT32 TempBase,
250 UINT32 Offset,
251 UINT8 *Buffer,
252 UINT32 Length
253 )
254 {
255 EFI_STATUS Status;
256 UINT32 FlashUnitLength;
257
258 FlashUnitLength = gFlashInfo[gIndex.InfIndex].BufferProgramSize << gFlashInfo[gIndex.InfIndex].ParallelNum;
259
260 if (0 == Length)
261 {
262 return EFI_SUCCESS;
263 }
264
265
266 if (Offset % FlashUnitLength)
267 {
268 UINT32 TempLength;
269
270
271 TempLength = FlashUnitLength - (Offset % FlashUnitLength);
272 if (TempLength > Length)
273 {
274 TempLength = Length;
275 }
276 Status = WriteAfterErase_Fill(Offset, Buffer, TempLength);
277 if (EFI_ERROR(Status))
278 {
279 DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: %r!\n", __FUNCTION__,__LINE__, Status));
280 return Status;
281 }
282
283 Offset += TempLength;
284 Length -= TempLength;
285 Buffer += TempLength;
286
287 //Desc:if Offset >= gOneFlashSize,modify base
288 if (0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
289 {
290 TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize;
291 gIndex.Base = TempBase;
292 Offset = 0;
293 }
294 }
295
296
297 Status = WriteAfterErase_Final(Offset, Buffer, Length);
298 if (EFI_ERROR(Status))
299 {
300 DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: %r!\n", __FUNCTION__,__LINE__, Status));
301 return Status;
302 }
303
304 return EFI_SUCCESS;
305 }
306
307
308 EFI_STATUS
FlashSectorErase(UINT32 TempBase,UINT32 Offset,UINT32 Length)309 FlashSectorErase(
310 UINT32 TempBase,
311 UINT32 Offset,
312 UINT32 Length
313 )
314 {
315 EFI_STATUS Status;
316 UINT32 SectorOffset;
317 UINT8 *StaticBuffer;
318 UINT8 *Buffer;
319 UINT32 TempOffset;
320 UINT32 TempLength;
321 UINT32 LeftLength;
322
323
324 if (0 == Length)
325 {
326 return EFI_SUCCESS;
327 }
328
329 LeftLength = gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum));
330 if (LeftLength < Length)
331 {
332 return EFI_UNSUPPORTED;
333 }
334
335
336 SectorOffset = Offset - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum));
337
338 Status = gBS->AllocatePool(EfiBootServicesData, gFlashInfo[gIndex.InfIndex].BlockSize * (UINTN)gFlashInfo[gIndex.InfIndex].ParallelNum, (VOID *)&StaticBuffer);
339 if (EFI_ERROR(Status))
340 {
341 return Status;
342 }
343
344 Buffer = StaticBuffer;
345
346 gBS->CopyMem((VOID *)Buffer, (VOID *)(UINTN)(TempBase + SectorOffset),
347 (gFlashInfo[gIndex.InfIndex].BlockSize * (UINTN)gFlashInfo[gIndex.InfIndex].ParallelNum));
348
349
350 Status = SectorErase(TempBase, SectorOffset);
351 if (EFI_ERROR(Status))
352 {
353 goto DO;
354 }
355
356
357 TempOffset = SectorOffset;
358 TempLength = Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum);
359
360 Status = WriteAfterErase(TempBase, TempOffset, Buffer, TempLength);
361 if (EFI_ERROR(Status))
362 {
363 goto DO;
364 }
365
366
367 Buffer = Buffer + TempLength + Length;
368 TempOffset = Offset + Length;
369 TempLength = SectorOffset + (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum) - TempOffset;
370
371 Status = WriteAfterErase(TempBase, TempOffset, Buffer, TempLength);
372 if (EFI_ERROR(Status))
373 {
374 DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: %r!\n", __FUNCTION__,__LINE__,Status));
375 goto DO;
376 }
377
378 (void)gBS->FreePool((VOID *)StaticBuffer);
379 return EFI_SUCCESS;
380
381 DO:
382 (void)gBS->FreePool((VOID *)StaticBuffer);
383 return Status;
384 }
385
386
387 EFI_STATUS
Erase(IN UNI_NOR_FLASH_PROTOCOL * This,IN UINT32 Offset,IN UINT32 Length)388 EFIAPI Erase(
389 IN UNI_NOR_FLASH_PROTOCOL *This,
390 IN UINT32 Offset,
391 IN UINT32 Length
392 )
393 {
394 EFI_STATUS Status = EFI_SUCCESS;
395 UINT32 Sectors;
396 UINT32 TempLength;
397 UINT32 TempBase;
398 UINT32 Loop;
399
400
401 if (Offset + Length > (gFlashInfo[gIndex.InfIndex].SingleChipSize * gFlashInfo[gIndex.InfIndex].ParallelNum))
402 {
403 DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Exceed the Flash Size!\n", __FUNCTION__,__LINE__));
404 return EFI_ABORTED;
405 }
406 if (0 == Length)
407 {
408 return EFI_SUCCESS;
409 }
410
411
412 Sectors = ((Offset + Length - 1) / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) - (Offset / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) + 1;
413 TempBase = gIndex.Base;
414
415 //if Offset >= gOneFlashSize,modify base
416 if(0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
417 {
418 TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize * (Offset/gFlashInfo[gIndex.InfIndex].SingleChipSize);
419 Offset = Offset - (Offset & gFlashInfo[gIndex.InfIndex].SingleChipSize);
420 }
421
422 for (Loop = 0; Loop <= Sectors; Loop ++)
423 {
424
425 TempLength = gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum));
426
427
428 if (TempLength > Length)
429 {
430 TempLength = Length;
431 }
432
433 Status = FlashSectorErase(TempBase, Offset, TempLength);
434 if (EFI_ERROR(Status))
435 {
436 DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: FlashErase One Sector Error, Status = %r!\n", __FUNCTION__,__LINE__,Status));
437 return Status;
438 }
439
440 Offset += TempLength;
441
442 //if Offset >= gOneFlashSize,modify base
443 if (0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
444 {
445 TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize;
446 Offset = 0;
447 }
448 Length -= TempLength;
449 }
450
451 return Status;
452 }
453
454
455 EFI_STATUS
Write(IN UNI_NOR_FLASH_PROTOCOL * This,IN UINT32 Offset,IN UINT8 * Buffer,UINT32 ulLength)456 EFIAPI Write(
457 IN UNI_NOR_FLASH_PROTOCOL *This,
458 IN UINT32 Offset,
459 IN UINT8 *Buffer,
460 UINT32 ulLength
461 )
462 {
463 EFI_STATUS Status;
464 UINT32 TempLength;
465 UINT32 TempBase;
466 UINT32 Loop;
467 UINT32 Sectors;
468
469 if((Offset + ulLength) > (gFlashInfo[gIndex.InfIndex].SingleChipSize * gFlashInfo[gIndex.InfIndex].ParallelNum))
470 {
471 DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Exceed the Flash Size!\n", __FUNCTION__,__LINE__));
472 return EFI_INVALID_PARAMETER;
473 }
474 if (0 == ulLength)
475 {
476 return EFI_SUCCESS;
477 }
478
479
480 Sectors = ((Offset + ulLength - 1) / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) - (Offset / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) + 1;
481 TempBase = gIndex.Base;
482
483 //if Offset >= gOneFlashSize,modify base
484 if(0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
485 {
486 TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize * (Offset/gFlashInfo[gIndex.InfIndex].SingleChipSize);
487 Offset = Offset - (Offset & gFlashInfo[gIndex.InfIndex].SingleChipSize);
488 }
489
490 for (Loop = 0; Loop <= Sectors; Loop ++)
491 {
492
493 TempLength = gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum));
494
495
496 if (TempLength > ulLength)
497 {
498 TempLength = ulLength;
499 }
500
501
502 if (TRUE == IsNeedToWrite(TempBase, Offset, Buffer, TempLength))
503 {
504 Status = FlashSectorErase(TempBase, Offset, TempLength);
505 if (EFI_ERROR(Status))
506 {
507 DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:FlashErase One Sector Error, Status = %r!\n", __FUNCTION__,__LINE__,Status));
508 return Status;
509 }
510
511
512 Status = WriteAfterErase(TempBase, Offset, Buffer, TempLength);
513 if (EFI_ERROR(Status))
514 {
515 DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:WriteAfterErase Status = %r!\n", __FUNCTION__,__LINE__,Status));
516 return Status;
517 }
518 }
519
520 Offset += TempLength;
521 Buffer += TempLength;
522
523 //if Offset >= gOneFlashSize,modify base
524 if (0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
525 {
526 TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize;
527 Offset = 0;
528 }
529 ulLength -= TempLength;
530 }
531
532 return EFI_SUCCESS;
533 }
534
535
SetFlashAttributeToUncache(VOID)536 VOID SetFlashAttributeToUncache(VOID)
537 {
538 EFI_CPU_ARCH_PROTOCOL *gCpu = NULL;
539 EFI_STATUS Status;
540
541 Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpu);
542 if (EFI_ERROR(Status))
543 {
544 DEBUG((EFI_D_ERROR, "LocateProtocol gEfiCpuArchProtocolGuid Status = %r !\n", Status));
545 }
546
547 Status = gCpu->SetMemoryAttributes(
548 gCpu,
549 PcdGet64(PcdNORFlashBase),
550 PcdGet32(PcdNORFlashCachableSize),
551 EFI_MEMORY_UC
552 );
553
554 if (EFI_ERROR(Status))
555 {
556 DEBUG((EFI_D_ERROR, "gCpu->SetMemoryAttributes Status = %r !\n", Status));
557 }
558
559 }
560
561 EFI_STATUS
InitializeFlash(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)562 EFIAPI InitializeFlash (
563 IN EFI_HANDLE ImageHandle,
564 IN EFI_SYSTEM_TABLE *SystemTable)
565 {
566 EFI_STATUS Status;
567
568
569 gIndex.Base = (UINT32)PcdGet64(PcdNORFlashBase);
570
571 SetFlashAttributeToUncache();
572 Status = FlashInit(gIndex.Base);
573 if (EFI_ERROR(Status))
574 {
575 DEBUG((EFI_D_ERROR, "Init Flash Error !\n"));
576 return Status;
577 }
578 else
579 {
580 DEBUG((EFI_D_ERROR, "Init Flash OK!\n"));
581 }
582
583 Status = gBS->InstallProtocolInterface (
584 &ImageHandle,
585 &gUniNorFlashProtocolGuid,
586 EFI_NATIVE_INTERFACE,
587 &gUniNorFlash);
588 if(EFI_SUCCESS != Status)
589 {
590 DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Install Protocol Interface %r!\n", __FUNCTION__,__LINE__,Status));
591 }
592
593 return Status;
594 }
595