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 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 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 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 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 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 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 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 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 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