123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594 |
- /** @file
- *
- * Copyright (c) 2015, Hisilicon Limited. All rights reserved.
- * Copyright (c) 2015, Linaro Limited. All rights reserved.
- *
- * This program and the accompanying materials
- * are licensed and made available under the terms and conditions of the BSD License
- * which accompanies this distribution. The full text of the license may be found at
- * http://opensource.org/licenses/bsd-license.php
- *
- * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
- *
- **/
- #include <Uefi.h>
- #include <Library/DebugLib.h>
- #include <Library/UefiBootServicesTableLib.h>
- #include <Library/ArmLib.h>
- #include <Library/PcdLib.h>
- #include <Protocol/NorFlashProtocol.h>
- #include <Library/DxeServicesTableLib.h>
- #include <Protocol/Cpu.h>
- #include "NorFlashHw.h"
- EFI_STATUS Erase(
- IN UNI_NOR_FLASH_PROTOCOL *This,
- IN UINT32 Offset,
- IN UINT32 Length
- );
- EFI_STATUS Write(
- IN UNI_NOR_FLASH_PROTOCOL *This,
- IN UINT32 Offset,
- IN UINT8 *Buffer,
- UINT32 ulLength
- );
- EFI_STATUS Read(
- IN UNI_NOR_FLASH_PROTOCOL *This,
- IN UINT32 Offset,
- IN OUT UINT8 *Buffer,
- IN UINT32 ulLen
- );
- UNI_NOR_FLASH_PROTOCOL gUniNorFlash = {
- Erase,
- Write,
- Read
- };
- EFI_STATUS
- EFIAPI Read(
- IN UNI_NOR_FLASH_PROTOCOL *This,
- IN UINT32 Offset,
- IN OUT UINT8 *Buffer,
- IN UINT32 ulLen
- )
- {
- UINT32 index;
- UINT64 ullAddr;
- UINT32 ullCnt = 0;
- UINT32 *puiBuffer32 = NULL;
- UINT32 *puiDst32 = NULL;
- UINT8 *pucBuffer8 = NULL;
- UINT8 *pucDst8 = NULL;
- if (Offset + ulLen > (gFlashInfo[gIndex.InfIndex].SingleChipSize * gFlashInfo[gIndex.InfIndex].ParallelNum))
- {
- DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Exceed the flash scope!\n", __FUNCTION__,__LINE__));
- return EFI_INVALID_PARAMETER;
- }
- if (0 == ulLen)
- {
- DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Length is Zero!\n", __FUNCTION__,__LINE__));
- return EFI_INVALID_PARAMETER;
- }
- if (NULL == Buffer)
- {
- DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Buffer is NULL!\n", __FUNCTION__,__LINE__));
- return EFI_BAD_BUFFER_SIZE;
- }
- ullAddr = gIndex.Base + Offset;
- pucBuffer8 = (UINT8 *)Buffer;
- pucDst8 = (UINT8 *)((UINTN)ullAddr);
- if (ulLen < FOUR_BYTE_UNIT)
- {
- for(index = 0; index< ulLen; index++)
- {
- *pucBuffer8++ = *pucDst8++;
- }
- }
- else
- {
- ullCnt = Offset % FOUR_BYTE_UNIT;
- ullCnt = FOUR_BYTE_UNIT - ullCnt;
- for(index = 0; index < ullCnt; index++)
- {
- *pucBuffer8++ = *pucDst8++;
- }
- ulLen -= ullCnt;
- puiBuffer32 = (UINT32 *)pucBuffer8;
- puiDst32 = (UINT32 *)pucDst8;
- ullCnt = ulLen / FOUR_BYTE_UNIT;
- for(index = 0; index < ullCnt; index++)
- {
- *puiBuffer32++ = *puiDst32++;
- }
- ullCnt = ulLen % FOUR_BYTE_UNIT;
- pucBuffer8 = (UINT8 *)puiBuffer32;
- pucDst8 = (UINT8 *)puiDst32;
- for(index = 0; index < ullCnt; index++)
- {
- *pucBuffer8++ = *pucDst8++;
- }
- }
- return EFI_SUCCESS;
- }
- static EFI_STATUS WriteAfterErase_Fill(
- IN const UINT32 Offset,
- IN const UINT8 *Buffer,
- IN const UINT32 Length
- )
- {
- EFI_STATUS Status;
- UINT32 Loop;
- UINT32 DataOffset;
- UINT32 NewOffset;
- UINT8 *NewDataUnit;
- UINT32 FlashUnitLength;
- FlashUnitLength = gFlashInfo[gIndex.InfIndex].BufferProgramSize << gFlashInfo[gIndex.InfIndex].ParallelNum;
- if (0 == Length)
- {
- return EFI_SUCCESS;
- }
- if ((Offset % FlashUnitLength + Length) > FlashUnitLength)
- {
- DEBUG ((EFI_D_INFO, "[%a]:[%dL]:Exceed the Flash Size!\n", __FUNCTION__,__LINE__));
- return EFI_UNSUPPORTED;
- }
- Status = gBS->AllocatePool(EfiBootServicesData, FlashUnitLength, (VOID *)&NewDataUnit);
- if (EFI_ERROR(Status))
- {
- DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Allocate Pool failed, %r!\n", __FUNCTION__,__LINE__, Status));
- return Status;
- }
- NewOffset = Offset - (Offset % FlashUnitLength);
- gBS->CopyMem((VOID *)NewDataUnit, (VOID *)(UINTN)(gIndex.Base + NewOffset), FlashUnitLength);
- DataOffset = Offset % FlashUnitLength;
- for (Loop = 0; Loop < Length; Loop ++)
- {
- NewDataUnit[(UINT32)(DataOffset + Loop)] = Buffer[Loop];
- }
- Status = BufferWrite(NewOffset, (void *)NewDataUnit, FlashUnitLength);
- if (EFI_ERROR(Status))
- {
- DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:BufferWrite %r!\n", __FUNCTION__,__LINE__, Status));
- return Status;
- }
- (void)gBS->FreePool((VOID *)NewDataUnit);
- return Status;
- }
- static EFI_STATUS WriteAfterErase_Final(
- IN UINT32 Offset,
- IN UINT8 *Buffer,
- IN UINT32 Length
- )
- {
- EFI_STATUS Status;
- UINT32 Loop;
- UINT32 FlashUnitLength;
- FlashUnitLength = gFlashInfo[gIndex.InfIndex].BufferProgramSize << gFlashInfo[gIndex.InfIndex].ParallelNum;
- if (0 == Length)
- {
- return EFI_SUCCESS;
- }
- if (0 != (Offset % FlashUnitLength))
- {
- DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: Offset must be a multiple of 0x%x!\n", __FUNCTION__,__LINE__,FlashUnitLength));
- return EFI_UNSUPPORTED;
- }
- Loop = Length / FlashUnitLength;
- while (Loop --)
- {
- Status = BufferWrite(Offset, (void *)Buffer, FlashUnitLength);
- if (EFI_ERROR(Status))
- {
- DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:BufferWrite Failed: %r!\n", __FUNCTION__,__LINE__, Status));
- return EFI_DEVICE_ERROR;
- }
- Offset += FlashUnitLength;
- Buffer += FlashUnitLength;
- }
- Length = Length % FlashUnitLength;
- if (Length)
- {
- Status = WriteAfterErase_Fill(Offset, Buffer, Length);
- if (EFI_ERROR(Status))
- {
- DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:WriteAfterErase_Fill failed,%r!\n", __FUNCTION__,__LINE__, Status));
- return Status;
- }
- }
- return EFI_SUCCESS;
- }
- EFI_STATUS
- WriteAfterErase(
- UINT32 TempBase,
- UINT32 Offset,
- UINT8 *Buffer,
- UINT32 Length
- )
- {
- EFI_STATUS Status;
- UINT32 FlashUnitLength;
- FlashUnitLength = gFlashInfo[gIndex.InfIndex].BufferProgramSize << gFlashInfo[gIndex.InfIndex].ParallelNum;
- if (0 == Length)
- {
- return EFI_SUCCESS;
- }
- if (Offset % FlashUnitLength)
- {
- UINT32 TempLength;
- TempLength = FlashUnitLength - (Offset % FlashUnitLength);
- if (TempLength > Length)
- {
- TempLength = Length;
- }
- Status = WriteAfterErase_Fill(Offset, Buffer, TempLength);
- if (EFI_ERROR(Status))
- {
- DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: %r!\n", __FUNCTION__,__LINE__, Status));
- return Status;
- }
- Offset += TempLength;
- Length -= TempLength;
- Buffer += TempLength;
- //Desc:if Offset >= gOneFlashSize,modify base
- if (0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
- {
- TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize;
- gIndex.Base = TempBase;
- Offset = 0;
- }
- }
- Status = WriteAfterErase_Final(Offset, Buffer, Length);
- if (EFI_ERROR(Status))
- {
- DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: %r!\n", __FUNCTION__,__LINE__, Status));
- return Status;
- }
- return EFI_SUCCESS;
- }
- EFI_STATUS
- FlashSectorErase(
- UINT32 TempBase,
- UINT32 Offset,
- UINT32 Length
- )
- {
- EFI_STATUS Status;
- UINT32 SectorOffset;
- UINT8 *StaticBuffer;
- UINT8 *Buffer;
- UINT32 TempOffset;
- UINT32 TempLength;
- UINT32 LeftLength;
- if (0 == Length)
- {
- return EFI_SUCCESS;
- }
- LeftLength = gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum));
- if (LeftLength < Length)
- {
- return EFI_UNSUPPORTED;
- }
- SectorOffset = Offset - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum));
- Status = gBS->AllocatePool(EfiBootServicesData, gFlashInfo[gIndex.InfIndex].BlockSize * (UINTN)gFlashInfo[gIndex.InfIndex].ParallelNum, (VOID *)&StaticBuffer);
- if (EFI_ERROR(Status))
- {
- return Status;
- }
- Buffer = StaticBuffer;
- gBS->CopyMem((VOID *)Buffer, (VOID *)(UINTN)(TempBase + SectorOffset),
- (gFlashInfo[gIndex.InfIndex].BlockSize * (UINTN)gFlashInfo[gIndex.InfIndex].ParallelNum));
- Status = SectorErase(TempBase, SectorOffset);
- if (EFI_ERROR(Status))
- {
- goto DO;
- }
- TempOffset = SectorOffset;
- TempLength = Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum);
- Status = WriteAfterErase(TempBase, TempOffset, Buffer, TempLength);
- if (EFI_ERROR(Status))
- {
- goto DO;
- }
- Buffer = Buffer + TempLength + Length;
- TempOffset = Offset + Length;
- TempLength = SectorOffset + (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum) - TempOffset;
- Status = WriteAfterErase(TempBase, TempOffset, Buffer, TempLength);
- if (EFI_ERROR(Status))
- {
- DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: %r!\n", __FUNCTION__,__LINE__,Status));
- goto DO;
- }
- (void)gBS->FreePool((VOID *)StaticBuffer);
- return EFI_SUCCESS;
- DO:
- (void)gBS->FreePool((VOID *)StaticBuffer);
- return Status;
- }
- EFI_STATUS
- EFIAPI Erase(
- IN UNI_NOR_FLASH_PROTOCOL *This,
- IN UINT32 Offset,
- IN UINT32 Length
- )
- {
- EFI_STATUS Status = EFI_SUCCESS;
- UINT32 Sectors;
- UINT32 TempLength;
- UINT32 TempBase;
- UINT32 Loop;
- if (Offset + Length > (gFlashInfo[gIndex.InfIndex].SingleChipSize * gFlashInfo[gIndex.InfIndex].ParallelNum))
- {
- DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Exceed the Flash Size!\n", __FUNCTION__,__LINE__));
- return EFI_ABORTED;
- }
- if (0 == Length)
- {
- return EFI_SUCCESS;
- }
- Sectors = ((Offset + Length - 1) / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) - (Offset / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) + 1;
- TempBase = gIndex.Base;
- //if Offset >= gOneFlashSize,modify base
- if(0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
- {
- TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize * (Offset/gFlashInfo[gIndex.InfIndex].SingleChipSize);
- Offset = Offset - (Offset & gFlashInfo[gIndex.InfIndex].SingleChipSize);
- }
- for (Loop = 0; Loop <= Sectors; Loop ++)
- {
- TempLength = gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum));
- if (TempLength > Length)
- {
- TempLength = Length;
- }
- Status = FlashSectorErase(TempBase, Offset, TempLength);
- if (EFI_ERROR(Status))
- {
- DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: FlashErase One Sector Error, Status = %r!\n", __FUNCTION__,__LINE__,Status));
- return Status;
- }
- Offset += TempLength;
- //if Offset >= gOneFlashSize,modify base
- if (0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
- {
- TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize;
- Offset = 0;
- }
- Length -= TempLength;
- }
- return Status;
- }
- EFI_STATUS
- EFIAPI Write(
- IN UNI_NOR_FLASH_PROTOCOL *This,
- IN UINT32 Offset,
- IN UINT8 *Buffer,
- UINT32 ulLength
- )
- {
- EFI_STATUS Status;
- UINT32 TempLength;
- UINT32 TempBase;
- UINT32 Loop;
- UINT32 Sectors;
- if((Offset + ulLength) > (gFlashInfo[gIndex.InfIndex].SingleChipSize * gFlashInfo[gIndex.InfIndex].ParallelNum))
- {
- DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Exceed the Flash Size!\n", __FUNCTION__,__LINE__));
- return EFI_INVALID_PARAMETER;
- }
- if (0 == ulLength)
- {
- return EFI_SUCCESS;
- }
- Sectors = ((Offset + ulLength - 1) / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) - (Offset / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) + 1;
- TempBase = gIndex.Base;
- //if Offset >= gOneFlashSize,modify base
- if(0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
- {
- TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize * (Offset/gFlashInfo[gIndex.InfIndex].SingleChipSize);
- Offset = Offset - (Offset & gFlashInfo[gIndex.InfIndex].SingleChipSize);
- }
- for (Loop = 0; Loop <= Sectors; Loop ++)
- {
- TempLength = gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum));
- if (TempLength > ulLength)
- {
- TempLength = ulLength;
- }
- if (TRUE == IsNeedToWrite(TempBase, Offset, Buffer, TempLength))
- {
- Status = FlashSectorErase(TempBase, Offset, TempLength);
- if (EFI_ERROR(Status))
- {
- DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:FlashErase One Sector Error, Status = %r!\n", __FUNCTION__,__LINE__,Status));
- return Status;
- }
- Status = WriteAfterErase(TempBase, Offset, Buffer, TempLength);
- if (EFI_ERROR(Status))
- {
- DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:WriteAfterErase Status = %r!\n", __FUNCTION__,__LINE__,Status));
- return Status;
- }
- }
- Offset += TempLength;
- Buffer += TempLength;
- //if Offset >= gOneFlashSize,modify base
- if (0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
- {
- TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize;
- Offset = 0;
- }
- ulLength -= TempLength;
- }
- return EFI_SUCCESS;
- }
- VOID SetFlashAttributeToUncache(VOID)
- {
- EFI_CPU_ARCH_PROTOCOL *gCpu = NULL;
- EFI_STATUS Status;
- Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpu);
- if (EFI_ERROR(Status))
- {
- DEBUG((EFI_D_ERROR, "LocateProtocol gEfiCpuArchProtocolGuid Status = %r !\n", Status));
- }
- Status = gCpu->SetMemoryAttributes(
- gCpu,
- PcdGet64(PcdNORFlashBase),
- PcdGet32(PcdNORFlashCachableSize),
- EFI_MEMORY_UC
- );
- if (EFI_ERROR(Status))
- {
- DEBUG((EFI_D_ERROR, "gCpu->SetMemoryAttributes Status = %r !\n", Status));
- }
- }
- EFI_STATUS
- EFIAPI InitializeFlash (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable)
- {
- EFI_STATUS Status;
- gIndex.Base = (UINT32)PcdGet64(PcdNORFlashBase);
- SetFlashAttributeToUncache();
- Status = FlashInit(gIndex.Base);
- if (EFI_ERROR(Status))
- {
- DEBUG((EFI_D_ERROR, "Init Flash Error !\n"));
- return Status;
- }
- else
- {
- DEBUG((EFI_D_ERROR, "Init Flash OK!\n"));
- }
- Status = gBS->InstallProtocolInterface (
- &ImageHandle,
- &gUniNorFlashProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &gUniNorFlash);
- if(EFI_SUCCESS != Status)
- {
- DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Install Protocol Interface %r!\n", __FUNCTION__,__LINE__,Status));
- }
- return Status;
- }
|