summaryrefslogtreecommitdiff
path: root/Core/EM/Runtime/Flash.c
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/Runtime/Flash.c')
-rw-r--r--Core/EM/Runtime/Flash.c1014
1 files changed, 1014 insertions, 0 deletions
diff --git a/Core/EM/Runtime/Flash.c b/Core/EM/Runtime/Flash.c
new file mode 100644
index 0000000..60dc9f2
--- /dev/null
+++ b/Core/EM/Runtime/Flash.c
@@ -0,0 +1,1014 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/em/Runtime/Flash.c 1 7/31/17 4:54a Chienhsieh $
+//
+// $Revision: 1 $
+//
+// $Date: 7/31/17 4:54a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/em/Runtime/Flash.c $
+//
+// 1 7/31/17 4:54a Chienhsieh
+// [TAG] EIP344536
+// [Description] SA40037 - BIOS update failure vulnerability
+// [Files] Flash.c
+//
+// 12 5/24/17 12:30p Felixp
+// Bug fixes from Aptio V are back ported to Aptio 4.
+// The following issues are addressed:
+// Bug fix(EIP 201329)
+// Symptom: FlashDriver_04 did not properly mark out/restore the _FVH
+// signature when updating a firmware volume
+// Root Cause: A logic error in the code that was attempting to match
+// the requested flash address update prevented
+// the code from removing/adding the _FVH signature from the memory
+// buffer.
+// Bug fix(EIP 217270)
+// Symptom: _FVH signature was not properly restored during update of
+// multiple sequential firmware volumes.
+// Root Cause: UpdatedArea[i].AreaSize was used before it was
+// initialized if multiple sequential FV were updated
+// by first erasing the entire flash area occupied by all FV and then
+// programming the area.
+// Bug fix
+// Symptom: _FVH signature was not properly restored when more than two
+// areas were simultaneously updated.
+// Root Cause: Logic error in FlashDriverDeviceWriteDisableExt
+// Bug fix in BeforeErase function: the function used wrong value to
+// corrupt the FV signature
+// Improvement: don't corrupt the signature when area block other than the
+// first one is erased.
+// The code that deletes/restores the FV signature is updated to restore
+// the signature only if it has actually
+// been deleted by a flash driver; the signature is not restored
+// otherwise.
+//
+// 11 9/12/13 4:24a Rameshr
+// [TAG] EIP136017
+// [Category] Improvement
+// [Description] Buffer Address updated if the partial block write
+// happens
+// [Files] Flash.c
+//
+// 10 11/11/11 3:06p Artems
+// Security: Copied ROM layout structure to SMM to avoid calls outside SMM
+//
+// 9 1/25/11 12:48p Oleksiyy
+// [TAG] EIP42253
+// [Category] New Feature
+// [Description] Added support for platforms, where flash part is not
+// memory mapped while write enabled, controlled by
+// NO_MMIO_FLASH_ACCESS_DURING_UPDATE sdl token. Flash protocol used to
+// access flash in that case.
+// [Files] NVRAMDXE.c, Flash.c, Tokens.c and Runtime.sdl
+//
+// 8 10/07/10 1:40p Felixp
+// Debug messages are removed.
+//
+// 7 10/07/10 12:07p Felixp
+// Bug fix:
+// Symptoms: The AFU reported verification error during update of
+// the FFS-based ROM hole that is the first FFS file in the firmware
+// volume(FV).
+// Details: The FV signature was not restored.
+// The flash driver logic that destroys and restores the FV signature
+// during the
+// FV update didn't cover the partial update case.
+// The Flash driver is updated to restore the signature during partial FV
+// updates.
+// The signature is now restored:
+// - In case of full FV update,
+// in the AfterWrite function once the last FV block is updated.
+// - In case of partial FV update,
+// in the FlashDriverDeviceWriteDisable function
+// The FlashDriverRead function is updated to return the valid signature
+// when
+// called in the middle of the FV update.
+//
+// 6 10/01/10 7:28p Felixp
+// Previous changes are rolled back. They break the recovery update.
+//
+// 4 9/24/10 8:01a Felixp
+// Definition of CRITICAL_SECTION is updated.
+//
+// 3 8/25/09 11:46p Felixp
+// Bug Fixes:
+// 1. Symptoms: AFUDOS was occasionally hanging in debug mode.
+// Details: Debug message funcation Trace, which uses boot time
+// services was used at runtime.
+// 2. Symptoms: Erase, Write, and Update functions of the Flash Protocol
+// did not work without prior call to DeviceWriteEnable protocol function.
+// Details: Nested call to DeviceWriteEnable was failing due to busy
+// critical section. Code is updated to use non-blocking internal write
+// enable function.
+// 3. Symptoms: DeviceWriteDisable did not work properly.
+// Details: Protocol interface structure was populated with wrong
+// function pointer.
+//
+// 2 7/09/09 5:29p Oleksiyy
+// Files clean-up, headers added
+//
+// 1 5/21/09 5:12p Felixp
+// Flash Driver
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Flash.c
+//
+// Description: Flash Driver Implementation
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#include <AmiDxeLib.h>
+#include <Flash.h>
+#include <Ffs.h>
+#include <RomLayout.h>
+#include <AmiHobs.h>
+#include <Protocol/FlashProtocol.h>
+
+typedef struct
+{
+ BOOLEAN Busy;
+ BOOLEAN SmiState;
+ UINT8 IntState[2];
+} CRITICAL_SECTION;
+
+typedef struct
+{
+ ROM_AREA *RomLayout;
+ UINT32 WriteEnableStatus;
+ CRITICAL_SECTION Cs;
+ UINT32 RomLayoutSize;
+} FLASH_DRIVER_MAILBOX;
+
+typedef struct
+{
+ FLASH_PROTOCOL Flash;
+ FLASH_DRIVER_MAILBOX *MailBox;
+} FLASH_PROTOCOL_PRIVATE;
+
+typedef struct
+{
+ ROM_AREA *RomArea;
+ UINT32 AreaSize ;
+ BOOLEAN RestoreSignature;
+} UPDATED_AREA_DESCRIPTOR;
+
+//-----Prototypes------------------------------------
+EFI_STATUS EFIAPI FlashDriverRead(
+ VOID* FlashAddress, UINTN Size, VOID* DataBuffer
+);
+EFI_STATUS EFIAPI FlashDriverErase(
+ VOID* FlashAddress, UINTN Size
+);
+EFI_STATUS EFIAPI FlashDriverWrite(
+ VOID* FlashAddress, UINTN Size, VOID* DataBuffer
+);
+EFI_STATUS EFIAPI FlashDriverUpdate(
+ VOID* FlashAddress, UINTN Size, VOID* DataBuffer
+);
+EFI_STATUS EFIAPI FlashDriverDeviceWriteEnable();
+EFI_STATUS EFIAPI FlashDriverDeviceWriteDisable();
+
+EFI_STATUS EFIAPI FlashDriverReadExt(
+ VOID* FlashAddress, UINTN Size, VOID* DataBuffer
+);
+EFI_STATUS EFIAPI FlashDriverEraseExt(
+ VOID* FlashAddress, UINTN Size
+);
+EFI_STATUS EFIAPI FlashDriverWriteExt(
+ VOID* FlashAddress, UINTN Size, VOID* DataBuffer
+);
+EFI_STATUS EFIAPI FlashDriverUpdateExt(
+ VOID* FlashAddress, UINTN Size, VOID* DataBuffer
+);
+EFI_STATUS EFIAPI FlashDriverDeviceWriteEnableExt();
+EFI_STATUS EFIAPI FlashDriverDeviceWriteDisableExt();
+
+extern const UINTN FlashEmpty;
+extern const BOOLEAN FlashNotMemoryMapped;
+
+#define BEGIN_CRITICAL_SECTION(Cs) \
+ { if ((Cs)->Busy) return EFI_ACCESS_DENIED;\
+ BeginCriticalSection(Cs);\
+ }
+#define END_CRITICAL_SECTION(Cs) EndCriticalSection(Cs)
+
+VOID BeginCriticalSection(CRITICAL_SECTION *Cs);
+VOID EndCriticalSection(CRITICAL_SECTION *Cs);
+
+//---Flash data protocole------------------------------------------
+FLASH_PROTOCOL_PRIVATE FlashData =
+{
+ {
+ FlashDriverReadExt, FlashDriverEraseExt, FlashDriverWriteExt, FlashDriverUpdateExt,
+ FlashDriverDeviceWriteEnableExt, FlashDriverDeviceWriteDisableExt
+ },
+ NULL
+};
+
+ROM_AREA *RomLayout = NULL;
+#define MAX_NUMBER_OF_UPDATED_AREAS 10
+UPDATED_AREA_DESCRIPTOR UpdatedArea[MAX_NUMBER_OF_UPDATED_AREAS];
+INT32 NumberOfUpdatedAreas=0;
+
+/*************** OUTSIDE SMM **********************************/
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: FlashDrvVirtAddressChange
+//
+// Description: Function updates the current pointer to FlashData protocol functions and
+// UpdatedArea pointed to by Address to be the proper value for the new address map
+//
+// Input:
+// IN EFI_EVENT Event Signalled event
+// IN VOID *Context Calling context
+//
+// Output: NON
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+VOID FlashDrvVirtAddressChange (
+ IN EFI_EVENT Event, IN VOID *Context
+)
+{
+ VOID **p;
+ INT32 i;
+ FlashVirtualFixup(pRS);
+ //Fixup protocol member functions
+ p=(VOID**)&FlashData.Flash.Write;
+
+ do
+ {
+ pRS->ConvertPointer(0, p++);
+ }
+ while (p!=(VOID**)&FlashData.Flash.DeviceWriteDisable);
+
+ pRS->ConvertPointer(0, &FlashData.MailBox);
+
+// if (RomLayout!=NULL) pRS->ConvertPointer(0, &RomLayout);
+
+ for (i=0; i<NumberOfUpdatedAreas; i++)
+ {
+ pRS->ConvertPointer(0, &UpdatedArea[i].RomArea);
+ }
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: FlashDriverInit
+//
+// Description: Creates necessary structures and instatlls Flash services before SMM mode.
+//
+// Input:
+// IN EFI_HANDLE ImageHandle Image Handle
+// IN EFI_SYSTEM_TABLE *SystemTable Pointer to System Table
+//
+// Output: EFI_STATUS
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS FlashDriverInit(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ static EFI_GUID HobListGuid = HOB_LIST_GUID;
+ static EFI_GUID AmiRomLayoutHobGuid = AMI_ROM_LAYOUT_HOB_GUID;
+ EFI_STATUS Status;
+ EFI_HANDLE Handler = NULL;
+ ROM_LAYOUT_HOB *RomLayoutHob;
+ UINTN MailboxSize = sizeof(FLASH_DRIVER_MAILBOX);
+ UINTN RomLayoutSize;
+
+ InitAmiRuntimeLib(ImageHandle, SystemTable, NULL, FlashDrvVirtAddressChange);
+
+//Create mailbox
+ VERIFY_EFI_ERROR(pBS->AllocatePool(EfiRuntimeServicesData, MailboxSize, (VOID **)&FlashData.MailBox));
+//Get ROM layout
+ RomLayoutHob = GetEfiConfigurationTable(SystemTable, &HobListGuid);
+ if (RomLayoutHob != NULL) {
+ if (!EFI_ERROR(FindNextHobByGuid(&AmiRomLayoutHobGuid, &RomLayoutHob))) {
+ ROM_AREA *Area;
+ RomLayoutSize = RomLayoutHob->Header.Header.HobLength - sizeof(ROM_LAYOUT_HOB);
+ VERIFY_EFI_ERROR(pBS->AllocatePool(EfiBootServicesData, RomLayoutSize, &RomLayout));
+ pBS->CopyMem(RomLayout, RomLayoutHob + 1, RomLayoutSize); //save ROM Layout for future use
+
+ for (Area = RomLayout; Area->Size != 0; Area++) { //update address
+ Area->Address -= FlashDeviceBase;
+ }
+
+ //pass ROM layout to SMM driver
+ FlashData.MailBox->RomLayout = RomLayout;
+ FlashData.MailBox->RomLayoutSize = (UINT32)RomLayoutSize;
+ } else {
+ FlashData.MailBox->RomLayout = NULL;
+ FlashData.MailBox->RomLayoutSize = 0;
+ }
+ }
+
+//Fill MailBox
+ FlashData.MailBox->WriteEnableStatus = 0;
+ FlashData.MailBox->Cs.Busy = FALSE;
+ FlashData.MailBox->Cs.SmiState = FALSE;
+ FlashData.MailBox->Cs.IntState[0] = 0;
+ FlashData.MailBox->Cs.IntState[1] = 0;
+
+ Status = pBS->InstallProtocolInterface(&Handler, &gFlashProtocolGuid, EFI_NATIVE_INTERFACE, &FlashData.Flash);
+
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+}
+
+/*************** INSIDE SMM **********************************/
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: FlashDriverSmmInit
+//
+// Description: Reinitialize necessary structures and instatlls Flash services in SMM mode.
+//
+// Input:
+// IN EFI_HANDLE ImageHandle Image Handle
+// IN EFI_SYSTEM_TABLE *SystemTable Pointer to System Table
+//
+// Output: EFI_STATUS
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS FlashDriverSmmInit(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handler = NULL;
+ FLASH_PROTOCOL_PRIVATE *NotSmmFlash;
+
+ VERIFY_EFI_ERROR(pBS->LocateProtocol(&gFlashProtocolGuid, NULL, &NotSmmFlash));
+
+//Reasign MailBox
+ FlashData.MailBox = NotSmmFlash->MailBox;
+
+//Save SMM copy of ROM layout
+ if(FlashData.MailBox->RomLayoutSize != 0) {
+ VERIFY_EFI_ERROR(pSmst->SmmAllocatePool(0, FlashData.MailBox->RomLayoutSize, &RomLayout));
+ pBS->CopyMem(RomLayout, FlashData.MailBox->RomLayout, FlashData.MailBox->RomLayoutSize);
+ }
+
+ Status = pBS->InstallProtocolInterface(&Handler, &gFlashSmmProtocolGuid, EFI_NATIVE_INTERFACE, &FlashData.Flash);
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+}
+
+/*************** INSIDE and OUSIDE SMM ************************/
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: BeforeErase
+//
+// Description: Invalidates FV by destroying the signature before erasing flash.
+//
+// Input:
+// VOID* FlashAddress Pointer to address of a flash
+//
+// Output: NON
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID BeforeErase(VOID* FlashAddress)
+{
+ ROM_AREA *Area;
+ UINT32 Data;
+
+ if ( RomLayout == NULL
+ || NumberOfUpdatedAreas == MAX_NUMBER_OF_UPDATED_AREAS
+ ) return;
+ //---For Areas in Rom Layout------------------------------------------
+ for (Area=RomLayout; Area->Size!=0; Area++)
+ {
+ //---If this is area we are looking for-------------------------------
+ if (Area->Address+FlashDeviceBase==(EFI_PHYSICAL_ADDRESS)(UINTN)FlashAddress)
+ {
+ if (Area->Type!=RomAreaTypeFv) return;
+
+ UpdatedArea[NumberOfUpdatedAreas].AreaSize = Area->Size;
+ UpdatedArea[NumberOfUpdatedAreas].RomArea = Area;
+ UpdatedArea[NumberOfUpdatedAreas++].RestoreSignature = FALSE;
+ // Invalidate FV by destroying the signature
+ Data = (UINT32)~FlashEmpty;
+ FlashDriverWrite(
+ &((EFI_FIRMWARE_VOLUME_HEADER*)FlashAddress)->Signature,
+ sizeof(UINT32),
+ &Data
+ );
+ return;
+ }
+ }
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: BeforeWrite
+//
+// Description: Invalidates FV by destroying the signature before writing to flash.
+//
+// Input:
+// VOID* FlashAddress Pointer to address of a flash
+// UINTN Size Size to write
+// VOID* DataBuffer Poiner to the Data Buffer
+//
+// Output: NON
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID BeforeWrite(VOID* FlashAddress, UINTN Size, VOID* DataBuffer)
+{
+ EFI_FIRMWARE_VOLUME_HEADER* Fv;
+ INT32 i;
+
+ for (i=0; i<NumberOfUpdatedAreas; i++)
+ {
+ //---Invalidate FV by destroying the signature
+ //---(alter data being programmed)
+ if ( UpdatedArea[i].RomArea->Address+FlashDeviceBase
+ ==(EFI_PHYSICAL_ADDRESS)(UINTN)FlashAddress
+ )
+ {
+ Fv = (EFI_FIRMWARE_VOLUME_HEADER*)DataBuffer;
+
+ if ( Size < sizeof(EFI_FIRMWARE_VOLUME_HEADER)
+ || Fv->Signature != FV_SIGNATURE
+ ) //The data being programmed is not FV, don't do anything
+ {
+ UpdatedArea[i] = UpdatedArea[NumberOfUpdatedAreas-1];
+ NumberOfUpdatedAreas--;
+ }
+
+ else
+ {
+ Fv->Signature = (UINT32)FlashEmpty;
+ UpdatedArea[i].AreaSize = (UINT32)Fv->FvLength;
+ UpdatedArea[i].RestoreSignature = TRUE;
+ }
+
+ return;
+ }
+ }
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: AfterWrite
+//
+// Description: Restores FV signature after writing to flash.
+//
+// Input:
+// VOID* FlashAddress Pointer to address of a flash
+// UINTN Size Size to write
+// VOID* DataBuffer Poiner to the Data Buffer
+//
+// Output: NON
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID AfterWrite(VOID* FlashAddress, UINTN Size, VOID* DataBuffer)
+{
+ EFI_PHYSICAL_ADDRESS Address;
+ EFI_PHYSICAL_ADDRESS AreaAddress;
+ INT32 i;
+
+ Address = (EFI_PHYSICAL_ADDRESS)(UINTN)FlashAddress;
+ for (i=0; i<NumberOfUpdatedAreas; i++)
+ {
+ AreaAddress = UpdatedArea[i].RomArea->Address+FlashDeviceBase;
+
+ if (AreaAddress==Address)
+ {
+ //Restore original data
+ ((EFI_FIRMWARE_VOLUME_HEADER*)DataBuffer)->Signature=FV_SIGNATURE;
+ }
+
+ if (AreaAddress+UpdatedArea[i].AreaSize==Address+Size)
+ {
+ UINT32 FvSignature = FV_SIGNATURE;
+ //Restore FV signature
+ FlashDriverWrite(
+ &((EFI_FIRMWARE_VOLUME_HEADER*)AreaAddress)->Signature,
+ sizeof(UINT32),
+ &FvSignature
+ );
+ UpdatedArea[i] = UpdatedArea[NumberOfUpdatedAreas-1];
+ NumberOfUpdatedAreas--;
+ }
+ }
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: AfterRead
+//
+// Description: Hook that is being called after the read operation.
+//
+// Input:
+// VOID* FlashAddress Pointer to address of a flash
+// UINTN Size Size to read
+//
+// Output: NON
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID AfterRead(VOID* FlashAddress, UINTN Size, VOID* DataBuffer)
+{
+ INT32 i;
+
+ if (FlashData.MailBox->WriteEnableStatus==0) return;
+ // If we are in the middle of flash update
+ // (FlashData.MailBox->WriteEnableStatus is not zero),
+ // it may happen that the FV signature has not been restored yet
+ // (typically happens during partial FV updates).
+ // Let's return the proper value. The signature will be restored later.
+ for (i=0; i<NumberOfUpdatedAreas; i++)
+ {
+ EFI_FIRMWARE_VOLUME_HEADER* Fv
+ = (EFI_FIRMWARE_VOLUME_HEADER*)(
+ UpdatedArea[i].RomArea->Address+FlashDeviceBase
+ );
+ if ( Fv == FlashAddress && Size >= EFI_FIELD_OFFSET(EFI_FIRMWARE_VOLUME_HEADER, Attributes))
+ {
+ ((EFI_FIRMWARE_VOLUME_HEADER*)DataBuffer)->Signature = FV_SIGNATURE;
+ return;
+ }
+ }
+}
+
+// Protocl Functions Implementation
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: FlashDriverRead
+//
+// Description: Implementation of the Read Function of the Flash protocol
+//
+// Input:
+// VOID* FlashAddress Pointer to address of a flash
+// UINTN Size Size to write
+// VOID* DataBuffer Poiner to the Data Buffer to write
+//
+// Output: NON
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS EFIAPI FlashDriverRead(
+ VOID* FlashAddress, UINTN Size, VOID* DataBuffer
+)
+{
+ BOOLEAN Status;
+
+ if (FlashData.MailBox->WriteEnableStatus!=0)
+ {
+ Status = FlashRead(FlashAddress, DataBuffer, (UINT32)Size);
+ }
+ else
+ {
+ UINTN i;
+
+ for (i=0; i<Size; i++)
+ ((UINT8*)DataBuffer)[i] = ((UINT8*)FlashAddress)[i];
+
+ Status = TRUE;
+ }
+ return (Status) ? EFI_SUCCESS : EFI_DEVICE_ERROR;
+}
+
+#define INT_SIZE sizeof(INTN)
+#define FLASH_EMPTY_BYTE ((UINT8)FlashEmpty)
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: IsClean
+//
+// Description: Function to loops through the buffer and check if it's empty
+//
+// Input:
+// IN UINT8* Address Pointer to address to check
+// IN UINTN Size Size of data to check
+//
+// Output: TRUE or FALSE
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+BOOLEAN IsClean(IN UINT8 *Address, IN UINTN Size)
+{
+ // loops through the buffer and check if it's empty
+ if (!( (UINTN)Address & (INT_SIZE-1) ))
+ {
+ for ( ; Size >= INT_SIZE; Size -= INT_SIZE, Address += INT_SIZE)
+ {
+ if (FlashNotMemoryMapped)
+ {
+ UINTN nData=0;
+ FlashDriverRead (Address, INT_SIZE, &(UINT8)nData );
+ if (nData != FlashEmpty) return FALSE;
+ }
+ else
+ if (*(UINTN*)Address != FlashEmpty) return FALSE;
+ }
+
+ }
+
+ // the address may not be INT_SIZE aligned
+ // check the remaining part of the buffer
+ for ( ; Size > 0; Size--, Address++)
+ {
+ if (FlashNotMemoryMapped)
+ {
+ UINT8 nData=0;
+ FlashDriverRead (Address, 1, &nData );
+ if (nData != FLASH_EMPTY_BYTE) return FALSE;
+ }
+ else
+ if (*Address != FLASH_EMPTY_BYTE) return FALSE;
+
+ }
+
+ return TRUE;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: FlashDriverErase
+//
+// Description: Implementation of the Erase Function of the Flash protocol
+//
+// Input:
+// VOID* FlashAddress Pointer to address of a flash to erase
+// UINTN Size Size to erase
+//
+// Output: EFI_SUCCESS or EFI_DEVICE_ERROR depending on result
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS EFIAPI FlashDriverErase(VOID* FlashAddress, UINTN Size)
+{
+ BOOLEAN Status = TRUE;
+ UINT8 *Address = (UINT8*)FlashAddress;
+
+ //---Enable write---------------------------------------------
+ FlashDriverDeviceWriteEnable();
+
+ for (; Status && Size>0; Address+=FlashBlockSize, Size-=FlashBlockSize)
+ {
+ //--- If block clean already - continue to next-----------
+ if (IsClean(Address, FlashBlockSize)) continue;
+ //---If not - Erase block---------------------------------
+ FlashBlockWriteEnable(Address);
+ Status=FlashEraseBlock(Address);
+ FlashBlockWriteDisable(Address);
+ }
+ //---Disable Write-------------------------------------------
+ FlashDriverDeviceWriteDisable();
+ return (Status) ? EFI_SUCCESS : EFI_DEVICE_ERROR;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: FlashDriverWrite
+//
+// Description: Implementation of the Write Function of the Flash protocol
+//
+// Input:
+// VOID* FlashAddress Pointer to address of a flash to write to
+// UINTN Size Size to write
+// VOID* DataBuffer - pointer to data to write to the flash part
+//
+// Output: EFI_SUCCESS or EFI_DEVICE_ERROR depending on result
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS EFIAPI FlashDriverWrite(
+ VOID* FlashAddress, UINTN Size, VOID* DataBuffer
+)
+{
+ BOOLEAN Status = TRUE;
+ UINT8 *Address = (UINT8*)FlashAddress;
+ UINT8 *Data = (UINT8*)DataBuffer;
+ UINT8 *BlockAddress = (UINT8*)BLOCK(Address); //Align to the block size
+ UINTN PartialSize;
+
+ FlashDriverDeviceWriteEnable();
+ //---If FlashAddress was not the begining of flash----------------
+ if (BlockAddress!=Address)
+ {
+ PartialSize = FlashBlockSize - (Address - BlockAddress);
+
+ if (PartialSize > Size) PartialSize = Size;
+ //---Write data and update address----------------------------
+ FlashBlockWriteEnable(BlockAddress);
+ Status=FlashProgram(Address, Data, (UINT32)PartialSize);
+ FlashBlockWriteDisable(BlockAddress);
+ Address = BlockAddress + FlashBlockSize;
+ Size -= PartialSize;
+ Data += PartialSize;
+ }
+ //---Else Write data and update address----------------------------
+ for (; Status && Size>=FlashBlockSize
+ ; Address+=FlashBlockSize, Size-=FlashBlockSize, Data+=FlashBlockSize
+ )
+ {
+ FlashBlockWriteEnable(Address);
+ Status=FlashProgram(Address, Data, FlashBlockSize);
+ FlashBlockWriteDisable(Address);
+ }
+ //--- If last chunk < FlashBlockSize-------------------------------
+ if (Size!=0 && Status)
+ {
+ FlashBlockWriteEnable(Address);
+ Status=FlashProgram(Address, Data, (UINT32)Size);
+ FlashBlockWriteDisable(Address);
+ }
+
+ FlashDriverDeviceWriteDisable();
+ return (Status) ? EFI_SUCCESS : EFI_DEVICE_ERROR;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: FlashDriverUpdate
+//
+// Description: Implementation of the Update Function of the Flash protocol
+//
+// Input:
+// VOID* FlashAddress Pointer to address of a flash to update (must be aligned to FlashBlockSize)
+// UINTN Size Size to update (must be multiple of FlashBlockSize)
+// VOID* DataBuffer - pointer to data to write to the flash part
+//
+// Output: EFI_SUCCESS or EFI_DEVICE_ERROR depending on result
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS EFIAPI FlashDriverUpdate(
+ VOID* FlashAddress, UINTN Size, VOID* DataBuffer
+)
+{
+ BOOLEAN Status = TRUE;
+ UINT8 *Address = (UINT8*)FlashAddress;
+ UINT8 *Data = (UINT8*)DataBuffer;
+
+ FlashDriverDeviceWriteEnable();
+
+ for (; Status && Size>=FlashBlockSize
+ ; Address+=FlashBlockSize, Size-=FlashBlockSize, Data+=FlashBlockSize
+ )
+ {
+ //---Writes a block checking is flash block clean or equal-----------
+ Status = FlashWriteBlock(Address, Data);
+ }
+
+ FlashDriverDeviceWriteDisable();
+ return (Status) ? EFI_SUCCESS : EFI_DEVICE_ERROR;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: FlashDriverDeviceWriteEnable
+//
+// Description: Enables writes to flash device
+//
+// Input: NON
+//
+//
+// Output: EFI_SUCCESS
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS EFIAPI FlashDriverDeviceWriteEnable()
+{
+ FlashData.MailBox->WriteEnableStatus++;
+
+ if (FlashData.MailBox->WriteEnableStatus==1)
+ {
+ FlashDeviceWriteEnable();
+ }
+
+ return EFI_SUCCESS;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: FlashDriverDeviceWriteDisable
+//
+// Description: Disables writes to flash device
+//
+// Input: NON
+//
+//
+// Output: EFI_SUCCESS
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS EFIAPI FlashDriverDeviceWriteDisable()
+{
+ if (FlashData.MailBox->WriteEnableStatus!=0)
+ {
+ FlashData.MailBox->WriteEnableStatus--;
+
+ if (FlashData.MailBox->WriteEnableStatus==0)
+ {
+ FlashDeviceWriteDisable();
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS EFIAPI FlashDriverReadExt(
+ VOID* FlashAddress, UINTN Size, VOID* DataBuffer
+){
+ EFI_STATUS Status;
+ BEGIN_CRITICAL_SECTION(&FlashData.MailBox->Cs);
+ Status = FlashDriverRead(FlashAddress,Size,DataBuffer);
+ AfterRead(FlashAddress, Size, DataBuffer);
+ END_CRITICAL_SECTION(&FlashData.MailBox->Cs);
+ return Status;
+}
+
+EFI_STATUS EFIAPI FlashDriverEraseExt(
+ VOID* FlashAddress, UINTN Size
+){
+ EFI_STATUS Status;
+
+ if (Size==0) return EFI_SUCCESS;
+ //---If Addres in not alligned properly or Size is not multiple to FlashBlockSize
+ //---Abort----------------------------------
+ if ((UINT8*)BLOCK(FlashAddress)!=FlashAddress || Size%FlashBlockSize!=0)
+ return EFI_UNSUPPORTED;
+
+ BEGIN_CRITICAL_SECTION(&FlashData.MailBox->Cs);
+ //---Invalidate FV by destroying the signature----------------
+ BeforeErase(FlashAddress);
+ Status = FlashDriverErase(FlashAddress, Size);
+ END_CRITICAL_SECTION(&FlashData.MailBox->Cs);
+ return Status;
+}
+
+EFI_STATUS EFIAPI FlashDriverWriteExt(
+ VOID* FlashAddress, UINTN Size, VOID* DataBuffer
+){
+ EFI_STATUS Status;
+ if (Size==0) return EFI_SUCCESS;
+
+ BEGIN_CRITICAL_SECTION(&FlashData.MailBox->Cs);
+ //---Invalidate FV by destroying the signature--------------------
+ BeforeWrite(FlashAddress, Size, DataBuffer);
+ Status = FlashDriverWrite(FlashAddress,Size,DataBuffer);
+ //---Restore FV signature-------------------------------------------
+ AfterWrite(FlashAddress, Size, DataBuffer);
+ END_CRITICAL_SECTION(&FlashData.MailBox->Cs);
+ return Status;
+}
+
+EFI_STATUS EFIAPI FlashDriverUpdateExt(
+ VOID* FlashAddress, UINTN Size, VOID* DataBuffer
+){
+ EFI_STATUS Status;
+
+ if (Size==0) return EFI_SUCCESS;
+
+ if ((UINT8*)BLOCK(FlashAddress)!=FlashAddress || Size%FlashBlockSize!=0)
+ return EFI_UNSUPPORTED;
+
+ BEGIN_CRITICAL_SECTION(&FlashData.MailBox->Cs);
+ BeforeErase(FlashAddress);
+ BeforeWrite(FlashAddress, Size, DataBuffer);
+ Status = FlashDriverUpdate(FlashAddress,Size,DataBuffer);
+ AfterWrite(FlashAddress, Size, DataBuffer);
+ END_CRITICAL_SECTION(&FlashData.MailBox->Cs);
+ return Status;
+}
+
+EFI_STATUS EFIAPI FlashDriverDeviceWriteEnableExt(){
+ EFI_STATUS Status;
+ BEGIN_CRITICAL_SECTION(&FlashData.MailBox->Cs);
+ Status = FlashDriverDeviceWriteEnable();
+ END_CRITICAL_SECTION(&FlashData.MailBox->Cs);
+ return Status;
+}
+
+EFI_STATUS EFIAPI FlashDriverDeviceWriteDisableExt(){
+ EFI_STATUS Status;
+ UINT32 OldWriteEnableStatus;
+
+ BEGIN_CRITICAL_SECTION(&FlashData.MailBox->Cs);
+ OldWriteEnableStatus = FlashData.MailBox->WriteEnableStatus;
+ Status = FlashDriverDeviceWriteDisable();
+ if (OldWriteEnableStatus!=0 && FlashData.MailBox->WriteEnableStatus==0)
+ {
+ // Before disabling the flash wtrites
+ // restore the destroyed FV signatures (if any).
+ // In case of full FV update, the FV signature is restored
+ // in the AfterWrite function once the last FV block is updated.
+ // In case of partial FV update when last FV block is not updated,
+ // the FV Signature is restored either here or in the BeforeRead function.
+ INT32 i;
+ for (i=0; i<NumberOfUpdatedAreas; i++)
+ {
+ if (UpdatedArea[i].RestoreSignature){
+ EFI_FIRMWARE_VOLUME_HEADER* Fv
+ = (EFI_FIRMWARE_VOLUME_HEADER*)(
+ UpdatedArea[i].RomArea->Address+FlashDeviceBase
+ );
+ UINT32 FvSignature = FV_SIGNATURE;
+ //Restore FV signature
+ FlashDriverWrite(
+ &Fv->Signature, sizeof(UINT32), &FvSignature
+ );
+ }
+ }
+ NumberOfUpdatedAreas = 0;
+ FlashDeviceWriteDisable();
+ }
+
+ END_CRITICAL_SECTION(&FlashData.MailBox->Cs);
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FlashDriverEntry
+//
+// Description: This function is the entry point for this module. This function
+// installs Flash protocols before and after SMM.
+//
+// Input: ImageHandle Image handle
+// SystemTable Pointer to the system table
+//
+// Output: Return Status based on errors that occurred while waiting for
+// time to expire.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS FlashDriverEntry(
+ IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ InitAmiLib(ImageHandle,SystemTable);
+ return InitSmmHandlerEx(
+ ImageHandle, SystemTable, FlashDriverSmmInit, FlashDriverInit
+ );
+}
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file