summaryrefslogtreecommitdiff
path: root/Board/Flash/STD
diff options
context:
space:
mode:
Diffstat (limited to 'Board/Flash/STD')
-rw-r--r--Board/Flash/STD/STDIntelFlashWrite.c699
-rw-r--r--Board/Flash/STD/StdFlash.cif12
-rw-r--r--Board/Flash/STD/StdFlash.mak71
-rw-r--r--Board/Flash/STD/StdFlash.sdl133
-rw-r--r--Board/Flash/STD/StdMxicFlashWrite.c698
-rw-r--r--Board/Flash/STD/StdSpansionFlashWrite.c669
6 files changed, 2282 insertions, 0 deletions
diff --git a/Board/Flash/STD/STDIntelFlashWrite.c b/Board/Flash/STD/STDIntelFlashWrite.c
new file mode 100644
index 0000000..2d1dbfc
--- /dev/null
+++ b/Board/Flash/STD/STDIntelFlashWrite.c
@@ -0,0 +1,699 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//*************************************************************************
+// $Header: /Alaska/SOURCE/Flash_Combined_2/Core/STD/STDIntelFlashWrite.c 6 12/23/09 6:13a Calvinchen $Revision:
+//
+// $Revision: 6 $
+//
+// $Date: 12/23/09 6:13a $Log: $
+//
+//
+//
+//**********************************************************************
+
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: StdIntelFlashWrite.c
+//
+// Description: Flash update routines
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+//----------------------------------------------------------------------
+// Includes
+#include <efi.h>
+#include <FlashPart.h>
+#include <AmiDxeLib.h>
+#include "token.h"
+
+//----------------------------------------------------------------------
+// define local MACROS
+
+//Flash Part Specific Tokens
+#define VENDOR_ID 0x88 // Intel Manufacturers ID
+#define DEVICE_ID64T 0x17 // 64M TB
+#define DEVICE_ID128T 0x18 // 128M TB
+#define DEVICE_ID256T 0x19 // 256M TB
+#define DEVICE_ID64B 0x1A // 64M BB
+#define DEVICE_ID128B 0x1B // 128M BB
+#define DEVICE_ID256B 0x1C // 256M BB
+
+//Flash Part Specific Tokens
+#define READ_ARRAY_CMD 0xff
+#define RD_STATUS_CMD 0x70
+#define CLR_STATUS_CMD 0x50
+#define ERASE_SET_CMD 0x20
+#define ERASE_CNF_CMD 0xd0
+#define PRG_SETUP_CMD 0x40
+
+#define RD_ID_CODE 0x90
+
+// Intel Status Register Bits
+#define VPP_LOW 0x08
+#define PROGRAM_FAIL 0x10
+#define ERASE_FAIL 0x20
+#define WSM_BUSY 0x80
+
+// Intel Lock Commands
+#define UNLOCK 0
+#define WRITE_LOCK 1
+
+//----------------------------------------------------------------------------
+// Module level global data
+extern UINT8 pFlashDeviceNumber[FLASH_PART_STRING_LENGTH];
+
+//----------------------------------------------------------------------------
+// Function Prototypes
+VOID
+IntelFlashEraseCommand (
+ volatile UINT8 *pBlockAddress
+ );
+VOID
+IntelFlashReadCommand (
+ volatile UINT8 *pByteAddress,
+ UINT8 *Data,
+ UINT32 *Length
+ );//{};
+VOID
+IntelFlashProgramCommand (
+ volatile UINT8 *pByteAddress,
+ UINT8 *Data,
+ UINT32 *Length
+ );
+BOOLEAN
+IntelFlashIsEraseCompleted (
+ volatile UINT8 *pBlockAddress,
+ BOOLEAN *pError,
+ UINTN *pStatus
+ );
+BOOLEAN
+IntelFlashIsProgramCompleted (
+ volatile UINT8 *pByteAddress,
+ UINT8 *Byte,
+ UINT32 Length,
+ BOOLEAN *pError,
+ UINTN *pStatus
+ );
+VOID
+IntelFlashBlockWriteEnable (
+ UINT8* pBlockAddress
+ );
+VOID
+IntelFlashBlockWriteDisable (
+ UINT8* pBlockAddress
+ );
+VOID
+IntelFlashDeviceWriteEnable (
+ VOID
+ );
+VOID
+IntelFlashDeviceWriteDisable (
+ VOID
+ );
+VOID
+IntelFlashVirtualFixup (
+ EFI_RUNTIME_SERVICES *pRS
+ );
+
+
+//========================================================================
+// Local Variable definitions
+
+// Flash Part Data structure fo the intel 82802ACC
+FLASH_PART mIntelSTD =
+ {
+ IntelFlashReadCommand,
+ IntelFlashEraseCommand,
+ IntelFlashProgramCommand,
+ IntelFlashIsEraseCompleted,
+ IntelFlashIsProgramCompleted,
+ IntelFlashBlockWriteEnable,
+ IntelFlashBlockWriteDisable,
+ IntelFlashDeviceWriteEnable,
+ IntelFlashDeviceWriteDisable,
+ IntelFlashVirtualFixup,
+ 1, // Number of bytes to program to the
+ // Flash part in each program command
+ 0, // Dummy value to hold place - only used in SPI
+ NULL // Flash Part Number Pointer
+ };
+
+
+
+//========================================================================
+// Function Definitions
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IntelSTDCmdDelay
+//
+// Description: This function resets the Sst flash part
+//
+// Input: None
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+IntelSTDCmdDelay (VOID)
+{
+ IoWrite8 ( 0xeb, 0x55 );
+ IoWrite8 ( 0xeb, 0xaa );
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IntelSTDResetFlash
+//
+// Description: This function resets the Sst flash part
+//
+// Input: None
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+IntelSTDResetFlash (
+ IN volatile UINT8* pAddress
+)
+{
+ *pAddress = READ_ARRAY_CMD;// Return to read mode
+ IntelSTDCmdDelay ();
+ *pAddress = CLR_STATUS_CMD;// clear status
+ IntelSTDCmdDelay ();
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IntelSTDOperationCompleted
+//
+// Description:
+// This function verifies whether the command sent to the FWH part
+// has completed and returns the status of the command
+//
+// Input:
+// IN volatile UINT8* pAddress Location to check the device status
+//
+// Output:
+// EFI_SUCCESS -
+// EFI_TIMEOUT -
+// EFI_DEVICE_ERROR -
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+EFI_STATUS
+IntelSTDOperationCompleted (
+ IN volatile UINT8* pAddress
+)
+{
+ UINT8 bSTDStatus;
+ UINT32 dTimeout = FLASH_RETRIES * 0x10000;
+
+ do {
+ *pAddress = RD_STATUS_CMD; // read status.
+ IntelSTDCmdDelay ();
+ bSTDStatus = *pAddress;
+ if ( bSTDStatus & WSM_BUSY ) {
+ if ( bSTDStatus & ( VPP_LOW + PROGRAM_FAIL + ERASE_FAIL ) )
+ return EFI_DEVICE_ERROR;
+ else return EFI_SUCCESS;
+ }
+ dTimeout--;
+ } while ( dTimeout != 0 );
+ return EFI_TIMEOUT;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IntelFlashEraseCommand
+//
+// Description: This API function erases a block in the flash. Flash model
+// specific code will branch out from this routine
+//
+// Input: pBlockAddress Block that need to be erased
+//
+// Output: Nothing
+//
+// Returns: None
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+IntelFlashEraseCommand (
+ IN volatile UINT8* pBlockAddress
+)
+{
+ EFI_STATUS Status;
+ UINT8 bFlashRetry;
+ UINT8 i;
+
+ for(i=0 ; i<4 ; i++) {
+ // Some block size is 32K
+ (UINT32)pBlockAddress += 0x8000;
+ IntelSTDResetFlash( pBlockAddress );
+ for ( bFlashRetry = 0; bFlashRetry < FLASH_RETRIES; bFlashRetry++ ) {
+ *pBlockAddress = ERASE_SET_CMD;
+ IntelSTDCmdDelay ();
+ *pBlockAddress = ERASE_CNF_CMD;
+ IntelSTDCmdDelay ();
+ Status = IntelSTDOperationCompleted( pBlockAddress );
+ IntelSTDResetFlash( pBlockAddress );
+ if ( Status != EFI_SUCCESS ) continue;
+ if ( *pBlockAddress != 0xFF ) Status = EFI_DEVICE_ERROR;
+ else {
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+ }
+//- return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IntelFlashIsEraseCompleted
+//
+// Description: This function verifies whether the block erase
+// command is completed and returns the status of the command
+//
+// Input: *pBlockAddress Location of the block erase
+//
+// Output: *pError True on error and false on success
+// *Status Error status code (0 - Success)
+//
+// Return: TRUE If operation completed successfully
+// *pError = FALSE, *pStatus = 0
+// FALSE If operation failed
+// *pError = TRUE, *pStatus = error status
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+BOOLEAN
+IntelFlashIsEraseCompleted (
+ IN volatile UINT8* pBlockAddress,
+ OUT BOOLEAN *pError,
+ OUT UINTN *pStatus
+)
+{
+ UINT32 dNumBytes;
+
+ for ( dNumBytes = 0; dNumBytes < FlashBlockSize; dNumBytes++ ) {
+ if ( *(volatile UINT8*)( pBlockAddress + dNumBytes ) != 0xFF ) {
+ if ( pError ) *pError = TRUE;
+ if ( pStatus ) *pStatus = EFI_DEVICE_ERROR;
+ return FALSE;
+ }
+ }
+ if ( pError ) *pError = FALSE;
+ if ( pStatus ) *pStatus = EFI_SUCCESS;
+ return TRUE;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IntelFlashProgramCommand
+//
+// Description: This function programs a byte data to the specified location
+//
+// Input: *pByteAddress Location where the data to be written
+// *Byte - Byte to be written
+// *Length - Number of bytes to write
+//
+// Output: *Length - Number of bytes still left to write
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+IntelFlashProgramCommand (
+ IN volatile UINT8* pByteAddress,
+ IN UINT8 *Byte,
+ IN OUT UINT32 *Length
+)
+{
+ UINT8 bFlashRetry;
+ EFI_STATUS Status;
+ UINT16 Word = 0;
+ UINT16* adjAddress;
+ BOOLEAN Program_Word = FALSE;
+
+ (UINT32)adjAddress = (UINT32)pByteAddress & 0xFFFFFFFE;
+ if (*pByteAddress != *Byte) {
+ // Word Program Only , Adjust Input word data
+ if((UINT32)pByteAddress & 1) {
+ // Get Last Byte of current address
+ Word = (*Byte) << 8;
+ Word += *(UINT8*)((UINT32)pByteAddress - 1);
+ } else {
+ if(*Length > 1) {
+ // Get Next Byte from Input Buffer
+ Word = *(Byte + 1) << 8;
+ Program_Word = TRUE;
+ } else {
+ // Get Next Byte of current address
+ Word = (*(UINT8*)((UINT32)pByteAddress + 1)) << 8;
+ }
+ Word += *Byte;
+ }
+ IntelSTDResetFlash( (volatile UINT8*)adjAddress );
+ for ( bFlashRetry = 0; bFlashRetry < FLASH_RETRIES; bFlashRetry++ ) {
+ *(UINT16*)adjAddress = PRG_SETUP_CMD; // Issue program command
+ IntelSTDCmdDelay ();
+ *(UINT16*)adjAddress = Word; // Program a Word
+ IntelSTDCmdDelay ();
+ // Check for completion of the program operation
+ Status = IntelSTDOperationCompleted( (volatile UINT8*)adjAddress );
+ IntelSTDResetFlash( (volatile UINT8*)adjAddress );
+ if ( Status != EFI_SUCCESS ) continue;
+ if ( *adjAddress != Word ) Status = EFI_DEVICE_ERROR;
+ else {
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+ // Input data is match
+ } else Status = EFI_SUCCESS;
+ if ( !Program_Word ) *Length = *Length - 1;
+ else *Length = *Length - 2;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IntelFlashIsProgramCompleted
+//
+// Description: This function verifies whether the program (page or byte)
+// command is completed and returns the status of the command
+//
+// Input: *pByteAddress Location of the program command
+// Byte Last data byte written
+//
+// Output: *pError True on error and false on success
+// *Status Error status code (0 - Success)
+//
+// Return: TRUE If operation completed successfully
+// *pError = FALSE, *pStatus = 0
+// FALSE If operation failed
+// *pError = TRUE, *pStatus = error status
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+BOOLEAN
+IntelFlashIsProgramCompleted (
+ IN volatile UINT8* pByteAddress,
+ IN UINT8 *Byte,
+ IN UINT32 Length,
+ OUT BOOLEAN *pError,
+ OUT UINTN *pStatus
+)
+{
+ UINT32 dNumBytes;
+ UINT8 bByte;
+
+ for ( dNumBytes = 0; dNumBytes < Length; dNumBytes++ ) {
+ bByte = * ( Byte + dNumBytes );
+ if ( bByte != *(volatile UINT8*)( pByteAddress + dNumBytes ) ) {
+ if ( pError ) *pError = TRUE;
+ if ( pStatus ) *pStatus = EFI_DEVICE_ERROR;
+ return FALSE;
+ }
+ }
+ if ( pError ) *pError = FALSE;
+ if ( pStatus ) *pStatus = EFI_SUCCESS;
+ return TRUE;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IntelFlashReadCommand
+//
+// Description: This function programs a byte data to the specified location
+//
+// Input: *pByteAddress Location where the data to be written
+// Bytes - data to be written.
+// Length - number of bytes to write
+//
+// Output: Length - number of bytes that were not written
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+IntelFlashReadCommand (
+ IN volatile UINT8* pByteAddress,
+ IN UINT8 *Byte,
+ IN UINT32 *Length
+)
+{
+ UINT32 dNumBytes = 0;
+
+ // Changes for SMIFlash module label "4.6.3.6_SMIFLASH_12" or later.
+ for ( dNumBytes = 0; dNumBytes < *Length ; dNumBytes++ )
+ *( Byte + dNumBytes ) = *(UINT8*)((UINT32)pByteAddress + dNumBytes );
+ *Length = 0;
+ return ;
+//- return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetBlockLock
+//
+// Description: This function programs a page of data at a time
+//
+// Input: *pBlockAddress - This is location where the data
+// is to be written
+// LockState - Value to use to set the Lock register for the
+// block defined by pBlockAddress
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+void
+SetBlockLock (
+ IN volatile UINT8* pBlockAddress,
+ IN UINT8 LockState
+)
+{
+//- // Update the block lock register
+//- ((UINT8 *)((UINTN)pBlockAddress - FlashDeviceBase
+//- + FwhFeatureSpaceBase))[2] = LockState;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IntelFlashBlockWriteEnable
+//
+// Description: This function contains any flash specific code need to
+// enable a particular flash block write
+//
+// Input: None
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+IntelFlashBlockWriteEnable (
+ IN UINT8* pBlockAddress
+)
+{
+//- SetBlockLock(pBlockAddress, UNLOCK);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IntelFlashBlockWriteDisable
+//
+// Description: This function contains any flash specific code need to
+// disable a particular flash block write
+//
+// Input: None
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+IntelFlashBlockWriteDisable (
+ IN UINT8* pBlockAddress
+)
+{
+//- SetBlockLock(pBlockAddress, WRITE_LOCK);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IntelFlashDeviceWriteEnable
+//
+// Description: This function contains any flash specific code need to
+// enable flash write
+//
+// Input: None
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+IntelFlashDeviceWriteEnable (VOID)
+{
+ //We don't have to do anything here because
+ //Flash Device is write enabled by the South Bridge driver
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IntelFlashDeviceWriteDisable
+//
+// Description: This function contains any flash specific code need to
+// disable flash write
+//
+// Input: None
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+IntelFlashDeviceWriteDisable (VOID)
+{
+ //We don't have to do anything here because
+ //we always keep flash device in the write enabled state
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IntelFlashVirtualFixup
+//
+// Description: This function will be invoked by the core to convert
+// runtime pointers to virtual address
+//
+// Input: *pRS Pointer to runtime services
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static
+VOID
+IntelFlashVirtualFixup (
+ IN EFI_RUNTIME_SERVICES *pRS
+)
+{
+// // Following is an example code for virtual address conversion
+// pRS->ConvertPointer(0, (VOID**)&FlashDeviceBase);
+
+ return;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IntelSTDIdentify
+//
+// Description: This function identifies the supported LPC flash parts and
+// returns appropriate flash device API pointer. If flash part is
+// not supported by this module it will return FALSE.
+//
+//
+// Input: pBlockAddress Block address of the flash part. Can be used to
+// send ID command
+//
+// Output: **FlashApi Pointer to hold the returned flash API
+//
+// Return: TRUE If flash part is supported, FlashApi contains
+// routines to handle the flash requests
+// FALSE Flash part is not supported
+//
+// Note: This routine is part of the global flash init list. Make sure
+// it is properly linked to the init list "FlashList" (in SDL file)
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN
+IntelSTDIdentify (
+ IN volatile UINT8* pBlockAddress,
+ OUT FLASH_PART **Struct
+)
+{
+ UINT8 VID, DID;
+
+//- SetBlockLock(pBlockAddress, UNLOCK);
+
+ *pBlockAddress = RD_ID_CODE;// Set to read ID code mode
+ VID = *pBlockAddress;
+ DID = *(pBlockAddress + 2);
+ *pBlockAddress = READ_ARRAY_CMD;// Return to read mode
+
+ if ((VID == VENDOR_ID) &&
+ (DID == DEVICE_ID64T || DID == DEVICE_ID128T || \
+ DID == DEVICE_ID256T || DID == DEVICE_ID64B || \
+ DID == DEVICE_ID128B || DID == DEVICE_ID256B)) {
+ // If your Block size is 128K, please modify your FLASH_BLOCK_SIZE
+ // to 128K in flash.sdl .
+ MemCpy ( pFlashDeviceNumber, "Numonyx 28F640/128/256P30B/T", 28 );
+ mIntelSTD.FlashPartNumber = pFlashDeviceNumber;
+ *Struct = &mIntelSTD;
+ return TRUE;
+ } else return FALSE;
+}
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Board/Flash/STD/StdFlash.cif b/Board/Flash/STD/StdFlash.cif
new file mode 100644
index 0000000..aee139f
--- /dev/null
+++ b/Board/Flash/STD/StdFlash.cif
@@ -0,0 +1,12 @@
+<component>
+ name = "STD Interface - Source"
+ category = ModulePart
+ LocalRoot = "Board\Flash\STD"
+ RefName = "STD_INTERFACE_SOURCE"
+[files]
+"StdFlash.sdl"
+"StdFlash.mak"
+"StdSpansionFlashWrite.c"
+"STDIntelFlashWrite.c"
+"StdMxicFlashWrite.c"
+<endComponent>
diff --git a/Board/Flash/STD/StdFlash.mak b/Board/Flash/STD/StdFlash.mak
new file mode 100644
index 0000000..cd8af53
--- /dev/null
+++ b/Board/Flash/STD/StdFlash.mak
@@ -0,0 +1,71 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+# $Header: /Alaska/SOURCE/Flash_Combined_2/Core/STD/StdFlash.mak 3 10/25/10 5:55a Calvinchen $Revision:
+#
+# $Date: 10/25/10 5:55a $Log:
+#
+#**********************************************************************
+
+#<AMI_FHDR_START>
+#
+# Name: FlashSrc.mak
+#
+# Description:
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+all : STDFlash
+
+STDFlash : $(BUILD_DIR)\StdFlash.mak StdFlashBin
+
+#---------------------------------------------------------------------------
+# Generic STD FLASH dependencies
+#---------------------------------------------------------------------------
+$(BUILD_DIR)\StdFlash.mak : $(STDFlash_DIR)\$(@B).cif $(STDFlash_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(STDFlash_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+#---------------------------------------------------------------------------
+# Create STD Flash Library
+#---------------------------------------------------------------------------
+StdFlashBin :
+ @set INCLUDE=%%INCLUDE%%
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\STDFlash.mak all\
+ "CFLAGS=$(CFLAGS:/W4=/W3)" \
+ NAME=STDFlash \
+ TYPE=LIBRARY LIBRARY_NAME=$(STDFLASHLIB)
+!IF "$(x64_BUILD)"=="1" && "$(BUILD_PEI_FLASH_LIB)"=="1"
+ $(MAKE) /$(MAKEFLAGS) BUILD_ROOT=$(BUILD_DIR)\
+ "EXT_OBJS=$(**:Build\=Build\IA32\)" PROJECT_DIR=$(PROJECT_DIR)\
+ /f $(BUILD_DIR)\STDFlash.mak all\
+ "CFLAGS=$(CFLAGS:/W4=/W3)"\
+ BUILD_DIR=$(BUILD_DIR)\IA32\
+ TYPE=PEI_LIBRARY NAME=STDFlash
+!ENDIF
+
+$(STDFLASHLIB) : STDFlash
+
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#************************************************************************* \ No newline at end of file
diff --git a/Board/Flash/STD/StdFlash.sdl b/Board/Flash/STD/StdFlash.sdl
new file mode 100644
index 0000000..298abaf
--- /dev/null
+++ b/Board/Flash/STD/StdFlash.sdl
@@ -0,0 +1,133 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2009, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+
+#**********************************************************************
+# $Header: /Alaska/SOURCE/Flash_Combined_2/Core/STD/StdFlash.sdl 4 11/02/09 4:35a Calvinchen $
+#
+# $Revision: 4 $
+#
+# $Date: 11/02/09 4:35a $
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Flash_Combined_2/Core/STD/StdFlash.sdl $
+#
+# 4 11/02/09 4:35a Calvinchen
+# Added support for MXIC 29LV640DB/T and SST SST39VF1681/1682.
+#
+# 3 6/24/09 3:15a Calvinchen
+# (EIP22177) Updated for Aptio Source Enhancement.
+#
+#
+#**********************************************************************
+
+TOKEN
+ Name = "STDFlash_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable STD Flash support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "STDFLASHLIB"
+ Value = "$(BUILD_DIR)\STDFlash.lib"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+TOKEN
+ Name = "Spansion_29GLxxx"
+ Value = "1"
+ Help = "This enables support for the SPANSION 29GL01G/512/256/128P STD flash parts"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "Numonyx_256P30x"
+ Value = "1"
+ Help = "This token enables support for the Numonyx 256P30x and AB flash parts"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "Mxic_29LVxxx"
+ Value = "1"
+ Help = "This token enables support for the MXIC 29LVxxx and SST 39VF16xx flash parts"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+PATH
+ Name = "STDFlash_DIR"
+End
+
+MODULE
+ Help = "Includes FlashSrc.mak to Project"
+ File = "STDFlash.mak"
+End
+
+ELINK
+ Name = "mStdSpansionIdentify,"
+ Parent = "FlashList"
+ Token = "Spansion_29GLxxx" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "IntelSTDIdentify,"
+ Parent = "FlashList"
+ Token = "Numonyx_256P30x" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "mStdMxicIdentify,"
+ Parent = "FlashList"
+ Token = "Mxic_29LVxxx" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\STDFlash.lib"
+ Parent = "$(Flash_DIR)\STDFlash.lib"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "$(Flash_DIR)\STDFlash.lib"
+ Parent = "FLASHLISTLIB"
+ InvokeOrder = AfterParent
+End
+
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2009, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#************************************************************************* \ No newline at end of file
diff --git a/Board/Flash/STD/StdMxicFlashWrite.c b/Board/Flash/STD/StdMxicFlashWrite.c
new file mode 100644
index 0000000..8271952
--- /dev/null
+++ b/Board/Flash/STD/StdMxicFlashWrite.c
@@ -0,0 +1,698 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//*************************************************************************
+// $Header: /Alaska/SOURCE/Flash_Combined_2/Core/STD/StdMxicFlashWrite.c 7 1/20/12 5:00a Calvinchen $
+//
+// $Revision: 7 $
+//
+// $Date: 1/20/12 5:00a $
+//*************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Flash_Combined_2/Core/STD/StdMxicFlashWrite.c $
+//
+// 7 1/20/12 5:00a Calvinchen
+// Added support for SST 39VF160x/320x.
+//
+// 6 7/21/11 5:11a Calvinchen
+//
+// 5 2/10/11 5:39a Calvinchen
+// [TAG] EIP50771
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Sometime vendor id return incorrect value.
+// [RootCause] There should have a 10ns delay according SSTVF1681
+// specification.
+// [Solution] Added an IO delay before read Vendor/Device ID.
+// [Files] StdMxicFlashWrite.c
+//
+// 4 12/23/09 6:13a Calvinchen
+// Improvement:
+// 1.Added FWH/LPC/STD Flash Device Number support.
+// 2.Changed for SMIFlash module Label "4.6.3.6_SMIFLASH_12" or later
+//
+// 3 12/15/09 5:50a Calvinchen
+// 1. Modified for adding flash chip name support.
+// 2. Bug fixed : Programming failed with SST 39VF1681.
+//
+// 2 11/16/09 1:51a Calvinchen
+//
+// 1 11/02/09 4:34a Calvinchen
+// Added support for MXIC 29LV640DB/T and SST SST39VF1681/1682.
+//
+//
+//
+//*************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: MxicFlashWrite.c
+//
+// Description: Flash update routines
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+//----------------------------------------------------------------------
+// Includes
+#include <efi.h>
+#include <AmiDxeLib.h>
+#include "FlashPart.h"
+#include "token.h"
+
+
+//----------------------------------------------------------------------
+// Local MACRO Definitions
+#define UNLOCK 0
+#define LOCK 1
+#define SECTOR_SIZE_8KB 0x2000 // 8kbytes sector size
+#define SECTOR_SIZE_64KB 0x10000 // 64kBytes sector size
+
+//----------------------------------------------------------------------------
+// Flash Part Specific Definitions
+
+#define Mx29LV640DB 0xcbc2
+#define Mx29LV640DT 0xc9c2
+#define Sst39VF1601 0x4bbf
+#define Sst39VF1602 0x4abf
+#define Sst39VF1681 0xc8bf
+#define Sst39VF1682 0xc9bf
+#define Sst39VF3201 0x5bbf
+#define Sst39VF3202 0x5abf
+#define Stm29W160ET 0xc420
+#define Stm29W160EB 0x4920
+
+//----------------------------------------------------------------------------
+// Module level global data
+extern UINT8 pFlashDeviceNumber[FLASH_PART_STRING_LENGTH];
+
+//----------------------------------------------------------------------------
+// Function Prototypes
+VOID
+MxicFlashEraseCommand (
+ volatile UINT8 *pBlockAddress
+ );
+VOID
+MxicFlashReadCommand (
+ volatile UINT8 *pByteAddress,
+ UINT8 *Data,
+ UINT32 *Length
+ );
+VOID
+MxicFlashProgramCommand (
+ volatile UINT8 *pByteAddress,
+ UINT8 *Data,
+ UINT32 *Length
+ );
+BOOLEAN
+MxicFlashIsEraseCompleted (
+ volatile UINT8 *pBlockAddress,
+ BOOLEAN *pError,
+ UINTN *pStatus
+ );
+BOOLEAN
+MxicFlashIsProgramCompleted (
+ volatile UINT8 *pByteAddress,
+ UINT8 *Byte,
+ UINT32 Length,
+ BOOLEAN *pError,
+ UINTN *pStatus
+ );
+VOID
+MxicFlashBlockWriteEnable (
+ UINT8* pBlockAddress
+ );
+VOID
+MxicFlashBlockWriteDisable (
+ UINT8* pBlockAddress
+ );
+VOID
+MxicFlashDeviceWriteEnable (
+ VOID
+ );
+VOID
+MxicFlashDeviceWriteDisable (
+ VOID
+ );
+VOID
+MxicFlashVirtualFixup (
+ EFI_RUNTIME_SERVICES *pRS
+ );
+
+extern FLASH_PART *FlashAPI;
+//----------------------------------------------------------------------------
+// Module specific variables
+FLASH_PART mStdMxicFlash =
+ {
+ MxicFlashReadCommand,
+ MxicFlashEraseCommand,
+ MxicFlashProgramCommand,
+ MxicFlashIsEraseCompleted,
+ MxicFlashIsProgramCompleted,
+ MxicFlashBlockWriteEnable,
+ MxicFlashBlockWriteDisable,
+ MxicFlashDeviceWriteEnable,
+ MxicFlashDeviceWriteDisable,
+ MxicFlashVirtualFixup, // Mxic flash device virtual address
+ // fix up routine
+ 1, // Number of bytes to program to the
+ // Flash part in each program command
+ SECTOR_SIZE_64KB, // Dummy value to hold place - only used in SPI
+ NULL // Flash Part Number Pointer
+ };
+
+//----------------------------------------------------------------------------
+// Function definitions
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MxicResetFlash
+//
+// Description: This function resets the Mxic flash part
+//
+// Input: None
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+MxicResetFlash (
+ IN volatile UINT8* pAddress
+)
+{
+ *pAddress = 0xf0;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MxicWriteBufferAbortReset
+//
+// Description: This function resets the Mxic flash part
+//
+// Input: None
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+MxicWriteBufferAbortReset (
+ IN volatile UINT8* pAddress
+)
+{
+ pAddress[0xaaa] = 0xaa;
+ pAddress[0x555] = 0x55;
+ pAddress[0xaaa] = 0xf0;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MxicFlashReadCommand
+//
+// Description: This function programs a byte data to the specified location
+//
+// Input: *pByteAddress Location where the data to be written
+// Bytes - data to be written.
+// Length - number of bytes to write
+//
+// Output: Length - number of bytes that were not written
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static
+VOID
+MxicFlashReadCommand (
+ IN volatile UINT8* pByteAddress,
+ OUT UINT8 *Byte,
+ OUT UINT32 *Length
+)
+{
+ UINT32 dNumBytes = 0;
+
+ // Changes for SMIFlash module label "4.6.3.6_SMIFLASH_12" or later.
+ for ( dNumBytes = 0; dNumBytes < *Length ; dNumBytes++ )
+ *( Byte + dNumBytes ) = *(UINT8*)((UINT32)pByteAddress + dNumBytes );
+ *Length = 0;
+ return ;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MxicStdWaitForOperationCompleted
+//
+// Description:
+// This function verifies whether the command sent to the FWH part
+// has completed and returns the status of the command
+//
+// Input:
+// IN volatile UINT8* pAddress Location to check the device status
+//
+// Output:
+// EFI_SUCCESS -
+// EFI_TIMEOUT -
+// EFI_DEVICE_ERROR -
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+EFI_STATUS
+MxicStdWaitForOperationCompleted (
+ IN volatile UINT8* pAddress
+)
+{
+ UINT8 bData1, bData2;
+ UINT32 dTimeout = FLASH_RETRIES * 0x1000000;
+ EFI_STATUS Status = EFI_TIMEOUT;
+
+ do {
+ bData1 = (*pAddress) & 0x40;
+ bData2 = (*pAddress) & 0x40;
+ if ( bData1 == bData2 ) return EFI_SUCCESS;
+ dTimeout--;
+ } while ( dTimeout != 0 ); // Check for Bit 6 Toggle
+
+ return EFI_TIMEOUT;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MxicFlashEraseCommand
+//
+// Description: This API function erases a block in the flash. Flash model
+// specific code will branch out from this routine
+//
+// Input: pBlockAddress Block that need to be erased
+//
+// Output: Nothing
+//
+// Returns: None
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+MxicFlashEraseCommand (
+ IN volatile UINT8* pBlockAddress
+)
+{
+ EFI_STATUS Status;
+ UINT8 bFlashRetry;
+ UINT16 wNumSectors, wSector;
+ UINT32 i;
+ volatile UINT8* pSectorAddr;
+
+ MxicWriteBufferAbortReset ( pBlockAddress );
+ wNumSectors = ( FlashBlockSize / FlashAPI->FlashSectorSize );
+ for ( wSector = 0; wSector < wNumSectors; wSector++ ) {
+ pSectorAddr = pBlockAddress + wSector * FlashAPI->FlashSectorSize;
+ for ( i = 0; i < FlashAPI->FlashSectorSize; i++ ) {
+ if ( *(pSectorAddr + i) != 0xFF ) break;
+ }
+ if ( i == FlashAPI->FlashSectorSize ) break;
+ for ( bFlashRetry = 0; bFlashRetry < FLASH_RETRIES; bFlashRetry++ ) {
+ pSectorAddr[0xaaa] = 0xaa;
+ pSectorAddr[0x555] = 0x55;
+ pSectorAddr[0xaaa] = 0x80;
+ pSectorAddr[0xaaa] = 0xaa;
+ pSectorAddr[0x555] = 0x55;
+ *pSectorAddr = 0x30;
+ Status = MxicStdWaitForOperationCompleted ( pSectorAddr );
+ MxicWriteBufferAbortReset ( pSectorAddr );
+ if ( Status != EFI_SUCCESS ) continue;
+ if ( *pSectorAddr != 0xFF ) Status = EFI_DEVICE_ERROR;
+ else {
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+ }
+//- return Status;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MxicFlashIsEraseCompleted
+//
+// Description: This function verifies whether the block erase
+// command is completed and returns the status of the command
+//
+// Input: *pBlockAddress Location of the block erase
+//
+// Output: *pError True on error and false on success
+// *Status Error status code (0 - Success)
+//
+// Return: TRUE If operation completed successfully
+// *pError = FALSE, *pStatus = 0
+// FALSE If operation failed
+// *pError = TRUE, *pStatus = error status
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+BOOLEAN
+MxicFlashIsEraseCompleted (
+ IN volatile UINT8 *pBlockAddress,
+ OUT BOOLEAN *pError,
+ OUT UINTN *pStatus
+)
+{
+ UINT32 dNumBytes;
+
+ for ( dNumBytes = 0; dNumBytes < FlashBlockSize; dNumBytes++ ) {
+ if ( *(volatile UINT8*)( pBlockAddress + dNumBytes ) != 0xFF ) {
+ if ( pError ) *pError = TRUE;
+ if ( pStatus ) *pStatus = EFI_DEVICE_ERROR;
+ return FALSE;
+ }
+ }
+ if ( pError ) *pError = FALSE;
+ if ( pStatus ) *pStatus = EFI_SUCCESS;
+ return TRUE;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MxicFlashProgramCommand
+//
+// Description: This function programs a byte data to the specified location
+//
+// Input: *pByteAddress - Location where the data to be written
+// *Byte - Byte to be written
+// *Length - Number of bytes to write
+//
+// Output: *Length - Number of bytes still left to write
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+MxicFlashProgramCommand (
+ IN volatile UINT8* pByteAddress,
+ IN UINT8 *Byte,
+ IN OUT UINT32 *Length
+)
+{
+ volatile UINT8* pBlockAddress = (volatile UINT8*)BLOCK(pByteAddress);
+ UINT8 bFlashRetry;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+
+ if ( *Byte != *pByteAddress ) {
+ MxicWriteBufferAbortReset ( pBlockAddress );
+ for ( bFlashRetry = 0; bFlashRetry < FLASH_RETRIES; bFlashRetry++ ) {
+ // Program Command Sequence
+ pBlockAddress[0xaaa] = 0xaa;
+ pBlockAddress[0x555] = 0x55;
+ pBlockAddress[0xaaa] = 0xa0;
+ *pByteAddress = *Byte;
+ Status = MxicStdWaitForOperationCompleted ( pBlockAddress );
+// MxicWriteBufferAbortReset ( pBlockAddress );
+ if ( Status != EFI_SUCCESS ) continue;
+ if ( *pByteAddress != *Byte ) Status = EFI_DEVICE_ERROR;
+ else {
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+ } else Status = EFI_SUCCESS;
+ *Length = *Length - 1;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MxicFlashIsProgramCompleted
+//
+// Description: This function verifies whether the program (page or byte)
+// command is completed and returns the status of the command
+//
+// Input: *pByteAddress Location of the program command
+// *Byte Pointer to data written
+// Length Amount of data to check
+//
+// Output: *pError True on error and false on success
+// *Status Error status code (0 - Success)
+//
+// Return: TRUE If operation completed successfully
+// *pError = FALSE, *pStatus = 0
+// FALSE If operation failed
+// *pError = TRUE, *pStatus = error status
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+BOOLEAN
+MxicFlashIsProgramCompleted (
+ IN volatile UINT8* pByteAddress,
+ IN UINT8 *Byte,
+ IN UINT32 Length,
+ OUT BOOLEAN *pError,
+ OUT UINTN *pStatus
+)
+{
+ UINT32 dNumBytes;
+ UINT8 bByte;
+
+ for ( dNumBytes = 0; dNumBytes < Length; dNumBytes++ ) {
+ bByte = * ( Byte + dNumBytes );
+ if ( bByte != *(volatile UINT8*)( pByteAddress + dNumBytes ) ) {
+ if ( pError ) *pError = TRUE;
+ if ( pStatus ) *pStatus = EFI_DEVICE_ERROR;
+ return FALSE;
+ }
+ }
+ if ( pError ) *pError = FALSE;
+ if ( pStatus ) *pStatus = EFI_SUCCESS;
+ return TRUE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MxicFlashBlockWriteEnable
+//
+// Description: This function contains any flash specific code need to
+// enable a particular flash block write
+//
+// Input: None
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+MxicFlashBlockWriteEnable (
+ IN UINT8* pBlockAddress
+)
+{
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MxicFlashBlockWriteDisable
+//
+// Description: This function contains any flash specific code need to
+// disable a particular flash block write
+//
+// Input: None
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+MxicFlashBlockWriteDisable (
+ IN UINT8* pBlockAddress
+)
+{
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MxicFlashDeviceWriteEnable
+//
+// Description: This function contains any flash specific code need to
+// enable flash write
+//
+// Input: None
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+MxicFlashDeviceWriteEnable (VOID)
+{
+ //We don't have to do anything here because
+ //Flash Device is write enabled by the South Bridge driver
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MxicFlashDeviceWriteDisable
+//
+// Description: This function contains any flash specific code need to
+// disable flash write
+//
+// Input: None
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+MxicFlashDeviceWriteDisable (VOID)
+{
+ //We don't have to do anything here because
+ //we always keep flash device in the write enabled state
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MxicFlashVirtualFixup
+//
+// Description: This function will be invoked by the core to convert
+// runtime pointers to virtual address
+//
+// Input: *pRS Pointer to runtime services
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static
+VOID
+MxicFlashVirtualFixup(
+ IN EFI_RUNTIME_SERVICES *pRS
+)
+{
+
+// // Following is an example code for virtual address conversion
+// pRS->ConvertPointer(0, (VOID**)&FlashDeviceBase);
+
+ return;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: mStdMxicIdentify
+//
+// Description: This function identifies the supported Mxic flash part and
+// returns appropriate flash device API pointer. If flash part is
+// not supported by this module it will return FALSE.
+//
+//
+// Input: pBlockAddress Block address of the flash part. Can be used to
+// send ID command
+//
+// Output: **FlashApi Pointer to hold the returned flash API
+//
+// Return: TRUE If flash part is supported, FlashApi contains
+// routines to handle the flash requests
+// FALSE Flash part is not supported
+//
+// Note: This routine is part of the global flash init list. Make sure
+// it is properly linked to the init list "FlashList" (in SDL file)
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN
+mStdMxicIdentify (
+ IN volatile UINT8* pBlockAddress,
+ OUT FLASH_PART **Struct
+)
+{
+ UINT8 bVenID, bDevID_1, bDevID_2;
+
+ MxicWriteBufferAbortReset( pBlockAddress );
+
+ pBlockAddress[0xaaa] = 0xaa;
+ pBlockAddress[0x555] = 0x55;
+ pBlockAddress[0xaaa] = 0x90;
+ // Delay before read flash ID.
+ IoWrite8 ( 0xeb, 0x55 );
+ bVenID = *pBlockAddress;
+ bDevID_1 = *(pBlockAddress + 0x01);
+ bDevID_2 = *(pBlockAddress + 0x02);
+
+ MxicWriteBufferAbortReset( pBlockAddress );
+
+ // Check for SST39VF1681/1682 support.
+ switch ((bDevID_1 << 8) + bVenID) {
+ case Sst39VF1601:
+ case Sst39VF1602:
+ case Sst39VF1681:
+ case Sst39VF1682:
+ case Sst39VF3201:
+ case Sst39VF3202:
+ MemCpy ( pFlashDeviceNumber, "SST 39VF1681/1682/3201/3202", 27 );
+ mStdMxicFlash.FlashPartNumber = pFlashDeviceNumber;
+ *Struct = &mStdMxicFlash;
+ return TRUE;
+ case Stm29W160ET:
+ case Stm29W160EB:
+ MemCpy ( pFlashDeviceNumber, "ST M29W160B/T", 13 );
+ mStdMxicFlash.FlashSectorSize = SECTOR_SIZE_8KB;
+ mStdMxicFlash.FlashPartNumber = pFlashDeviceNumber;
+ *Struct = &mStdMxicFlash;
+ return TRUE;
+ }
+ // Check for Mxic 29LV640DB/T support.
+ switch ((bDevID_2 << 8) + bVenID) {
+ case Mx29LV640DB:
+ case Mx29LV640DT:
+ MemCpy ( pFlashDeviceNumber, "MXIC 29LV640B/T", 15 );
+ mStdMxicFlash.FlashPartNumber = pFlashDeviceNumber;
+ *Struct = &mStdMxicFlash;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Board/Flash/STD/StdSpansionFlashWrite.c b/Board/Flash/STD/StdSpansionFlashWrite.c
new file mode 100644
index 0000000..1bb80d5
--- /dev/null
+++ b/Board/Flash/STD/StdSpansionFlashWrite.c
@@ -0,0 +1,669 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//*************************************************************************
+// $Header: /Alaska/SOURCE/Flash_Combined_2/Core/STD/StdSpansionFlashWrite.c 8 2/10/11 5:37a Calvinchen $
+//
+// $Revision: 8 $
+//
+// $Date: 2/10/11 5:37a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Flash_Combined_2/Core/STD/StdSpansionFlashWrite.c $
+//
+// 8 2/10/11 5:37a Calvinchen
+// [TAG] EIP50771
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Sometime vendor id return incorrect value.
+// [RootCause] There should have a 10ns delay according SSTVF1681
+// specification.
+// [Solution] Added an IO Delay before get vendor/Device i.
+// [Files] StdSpansionFlashWrite.c
+//
+// 7 12/23/09 6:13a Calvinchen
+// Improvement:
+// 1.Added FWH/LPC/STD Flash Device Number support.
+// 2.Changed for SMIFlash module Label "4.6.3.6_SMIFLASH_12" or later
+//
+// 6 12/15/09 5:50a Calvinchen
+// 1. Modified for adding flash chip name support.
+// 2. Bug fixed : Programming failed with SST 39VF1681.
+//
+// 5 6/24/09 3:15a Calvinchen
+// (EIP22177) Updated for Aptio Source Enhancement.
+//
+// 2 1/14/09 10:37p Calvinchen
+//
+// 1 12/11/08 2:18a Calvinchen
+// Added support for Spansion 29GL128/256/512/01GP STD flash.
+//
+//
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//
+// Name: SpansionFlashWrite.c
+//
+// Description: Flash update routines
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+//----------------------------------------------------------------------
+// Includes
+#include <efi.h>
+#include <AmiDxeLib.h>
+#include "FlashPart.h"
+#include "token.h"
+
+
+//----------------------------------------------------------------------
+// Local MACRO Definitions
+#define UNLOCK 0
+#define LOCK 1
+
+//----------------------------------------------------------------------------
+// Flash Part Specific Definitions
+
+#define S29GL01GP_MANID 0x01 // offset 0x00 = Manufacturers ID
+#define S29GL01GP_DEVID1 0x7e // offset 0x02 = Device ID byte 1
+#define S29GL01GP_DEVID2 0x28 // offset 0x1c = Device ID byte 2
+#define S29GL01GP_DEVID3 0x01 // offset 0x1e = Device ID byte 3
+#define Spansion29GLxxx 0x7e01
+
+//----------------------------------------------------------------------------
+// Module level global data
+extern UINT8 pFlashDeviceNumber[FLASH_PART_STRING_LENGTH];
+
+//----------------------------------------------------------------------------
+// Function Prototypes
+VOID
+SpansionFlashEraseCommand (
+ volatile UINT8 *pBlockAddress
+ );
+VOID
+SpansionFlashReadCommand (
+ volatile UINT8 *pByteAddress,
+ UINT8 *Data,
+ UINT32 *Length
+ );
+VOID
+SpansionFlashProgramCommand (
+ volatile UINT8 *pByteAddress,
+ UINT8 *Data,
+ UINT32 *Length
+ );
+BOOLEAN
+SpansionFlashIsEraseCompleted (
+ volatile UINT8 *pBlockAddress,
+ BOOLEAN *pError,
+ UINTN *pStatus
+ );
+BOOLEAN
+SpansionFlashIsProgramCompleted (
+ volatile UINT8 *pByteAddress,
+ UINT8 *Byte,
+ UINT32 Length,
+ BOOLEAN *pError,
+ UINTN *pStatus
+ );
+VOID
+SpansionFlashBlockWriteEnable (
+ UINT8* pBlockAddress
+ );
+VOID
+SpansionFlashBlockWriteDisable (
+ UINT8* pBlockAddress
+ );
+VOID
+SpansionFlashDeviceWriteEnable (
+ VOID
+ );
+VOID
+SpansionFlashDeviceWriteDisable (
+ VOID
+ );
+VOID
+SpansionFlashVirtualFixup (
+ EFI_RUNTIME_SERVICES *pRS
+ );
+
+
+
+//----------------------------------------------------------------------------
+// Module specific variables
+FLASH_PART mStdSpansionFlash =
+ {
+ SpansionFlashReadCommand,
+ SpansionFlashEraseCommand,
+ SpansionFlashProgramCommand,
+ SpansionFlashIsEraseCompleted,
+ SpansionFlashIsProgramCompleted,
+ SpansionFlashBlockWriteEnable,
+ SpansionFlashBlockWriteDisable,
+ SpansionFlashDeviceWriteEnable,
+ SpansionFlashDeviceWriteDisable,
+ SpansionFlashVirtualFixup, // Spansion flash device virtual address
+ // fix up routine
+ 1, // Number of bytes to program to the
+ // Flash part in each program command
+ 0, // Dummy value to hold place - only used in SPI
+ NULL // Flash Part Number Pointer
+ };
+
+//----------------------------------------------------------------------------
+// Function definitions
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SpansionResetFlash
+//
+// Description: This function resets the Spansion flash part
+//
+// Input: None
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+SpansionResetFlash (
+ IN volatile UINT8* pAddress
+)
+{
+ *pAddress = 0xf0;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SpansionWriteBufferAbortReset
+//
+// Description: This function resets the Spansion flash part
+//
+// Input: None
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+SpansionWriteBufferAbortReset (
+ IN volatile UINT8* pAddress
+)
+{
+ pAddress[0xaaa] = 0xaa;
+ pAddress[0x555] = 0x55;
+ pAddress[0x555] = 0xf0;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SpansionFlashReadCommand
+//
+// Description: This function programs a byte data to the specified location
+//
+// Input: *pByteAddress Location where the data to be written
+// Bytes - data to be written.
+// Length - number of bytes to write
+//
+// Output: Length - number of bytes that were not written
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static
+VOID
+SpansionFlashReadCommand (
+ IN volatile UINT8* pByteAddress,
+ OUT UINT8 *Byte,
+ OUT UINT32 *Length
+)
+{
+ UINT32 dNumBytes = 0;
+
+ // Changes for SMIFlash module label "4.6.3.6_SMIFLASH_12" or later.
+ for ( dNumBytes = 0; dNumBytes < *Length ; dNumBytes++ )
+ *( Byte + dNumBytes ) = *(UINT8*)((UINT32)pByteAddress + dNumBytes );
+ *Length = 0;
+ return ;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: WaitForPollingCompleted
+//
+// Description:
+// This function waits until the command sent to the flash part
+// has completed
+//
+// Input:
+// IN volatile UINT8* pAddress Location to check the device status
+// IN UINT8 bData Polling Data
+//
+// Output: Nothing
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+EFI_STATUS
+WaitForPollingCompleted (
+ IN volatile UINT8* pAddress,
+ IN UINT8 bData
+)
+{
+ UINT8 bStatus;
+ UINT32 dTimeout = FLASH_RETRIES * 0x10000;
+ EFI_STATUS Status = EFI_TIMEOUT;
+
+ for ( ; dTimeout > 0; dTimeout-- ) {
+ // Read DQ0~7
+ bStatus = *(volatile UINT8*)pAddress;
+ // Check DQ7 for Polling completed.
+ if ((bStatus & BIT07) == (bData & BIT07)) return EFI_SUCCESS;
+ // Check DQ5(Write Timeout),DQ3(Erase Timeout) and DQ1(Abort) for
+ // error occured.
+ if ( (bStatus & BIT05) || (bStatus & BIT03) || (bStatus & BIT01) ) {
+ bStatus = *(volatile UINT8*)pAddress;
+ if ((bStatus & BIT07) == (bData & BIT07)) return EFI_SUCCESS;
+ else return EFI_TIMEOUT;
+ }
+ }
+ return EFI_DEVICE_ERROR;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SpansionFlashEraseCommand
+//
+// Description: This API function erases a block in the flash. Flash model
+// specific code will branch out from this routine
+//
+// Input: pBlockAddress Block that need to be erased
+//
+// Output: Nothing
+//
+// Returns: None
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+SpansionFlashEraseCommand (
+ IN volatile UINT8* pBlockAddress
+)
+{
+ EFI_STATUS Status;
+ UINT8 bFlashRetry;
+
+ for ( bFlashRetry = 0; bFlashRetry < FLASH_RETRIES; bFlashRetry++ ) {
+ SpansionResetFlash ( pBlockAddress );
+ pBlockAddress[0xaaa] = 0xaa;
+ pBlockAddress[0x555] = 0x55;
+ pBlockAddress[0xaaa] = 0x80;
+ pBlockAddress[0xaaa] = 0xaa;
+ pBlockAddress[0x555] = 0x55;
+ *pBlockAddress = 0x30;
+ Status = WaitForPollingCompleted ( pBlockAddress, 0xff );
+ if ( Status != EFI_SUCCESS ) SpansionResetFlash ( pBlockAddress );
+ if ( *pBlockAddress == 0xFF ) {
+ Status = EFI_SUCCESS;
+ break;
+ } else Status = EFI_DEVICE_ERROR;
+ }
+//- return Status;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SpansionFlashIsEraseCompleted
+//
+// Description: This function verifies whether the block erase
+// command is completed and returns the status of the command
+//
+// Input: *pBlockAddress Location of the block erase
+//
+// Output: *pError True on error and false on success
+// *Status Error status code (0 - Success)
+//
+// Return: TRUE If operation completed successfully
+// *pError = FALSE, *pStatus = 0
+// FALSE If operation failed
+// *pError = TRUE, *pStatus = error status
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+BOOLEAN
+SpansionFlashIsEraseCompleted (
+ IN volatile UINT8 *pBlockAddress,
+ OUT BOOLEAN *pError,
+ OUT UINTN *pStatus
+)
+{
+ UINT32 dNumBytes;
+
+ for ( dNumBytes = 0; dNumBytes < FlashBlockSize; dNumBytes++ ) {
+ if ( *(volatile UINT8*)( pBlockAddress + dNumBytes ) != 0xFF ) {
+ if ( pError ) *pError = TRUE;
+ if ( pStatus ) *pStatus = EFI_DEVICE_ERROR;
+ return FALSE;
+ }
+ }
+ if ( pError ) *pError = FALSE;
+ if ( pStatus ) *pStatus = EFI_SUCCESS;
+ return TRUE;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SpansionFlashProgramCommand
+//
+// Description: This function programs a byte data to the specified location
+//
+// Input: *pByteAddress - Location where the data to be written
+// *Byte - Byte to be written
+// *Length - Number of bytes to write
+//
+// Output: *Length - Number of bytes still left to write
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+SpansionFlashProgramCommand (
+ IN volatile UINT8* pByteAddress,
+ IN UINT8 *Byte,
+ IN OUT UINT32 *Length
+)
+{
+ volatile UINT8* pBlockAddress = (volatile UINT8*)BLOCK(pByteAddress);
+ UINT8 bFlashRetry;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+
+ if ( *Byte != *pByteAddress ) {
+ SpansionResetFlash ( pBlockAddress );
+ for ( bFlashRetry = 0; bFlashRetry < FLASH_RETRIES; bFlashRetry++ ) {
+ // Program Command Sequence - Write to Buffer
+ pBlockAddress[0xaaa] = 0xaa;
+ pBlockAddress[0x555] = 0x55;
+ *pByteAddress = 0x25; // write to buffer command.
+ *pByteAddress = 0; // write count - 1
+ *pByteAddress = *Byte; //
+ *pByteAddress = 0x29; // program buffer to flash command.
+ Status = WaitForPollingCompleted ( pByteAddress, *Byte );
+ if ( Status == EFI_TIMEOUT ) {
+ SpansionWriteBufferAbortReset ( pBlockAddress );
+ continue;
+ }
+ if ( Status == EFI_DEVICE_ERROR )
+ SpansionResetFlash ( pByteAddress );
+ if ( *pByteAddress == *Byte ) {
+ Status = EFI_SUCCESS;
+ break;
+ } else Status = EFI_DEVICE_ERROR;
+ }
+ } else Status = EFI_SUCCESS;
+ *Length = *Length - 1;
+ //- return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SpansionFlashIsProgramCompleted
+//
+// Description: This function verifies whether the program (page or byte)
+// command is completed and returns the status of the command
+//
+// Input: *pByteAddress Location of the program command
+// *Byte Pointer to data written
+// Length Amount of data to check
+//
+// Output: *pError True on error and false on success
+// *Status Error status code (0 - Success)
+//
+// Return: TRUE If operation completed successfully
+// *pError = FALSE, *pStatus = 0
+// FALSE If operation failed
+// *pError = TRUE, *pStatus = error status
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+BOOLEAN
+SpansionFlashIsProgramCompleted (
+ IN volatile UINT8* pByteAddress,
+ IN UINT8 *Byte,
+ IN UINT32 Length,
+ OUT BOOLEAN *pError,
+ OUT UINTN *pStatus
+)
+{
+ UINT32 dNumBytes;
+ UINT8 bByte;
+
+ for ( dNumBytes = 0; dNumBytes < Length; dNumBytes++ ) {
+ bByte = * ( Byte + dNumBytes );
+ if ( bByte != *(volatile UINT8*)( pByteAddress + dNumBytes ) ) {
+ if ( pError ) *pError = TRUE;
+ if ( pStatus ) *pStatus = EFI_DEVICE_ERROR;
+ return FALSE;
+ }
+ }
+ if ( pError ) *pError = FALSE;
+ if ( pStatus ) *pStatus = EFI_SUCCESS;
+ return TRUE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SpansionFlashBlockWriteEnable
+//
+// Description: This function contains any flash specific code need to
+// enable a particular flash block write
+//
+// Input: None
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+SpansionFlashBlockWriteEnable (
+ IN UINT8* pBlockAddress
+)
+{
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SpansionFlashBlockWriteDisable
+//
+// Description: This function contains any flash specific code need to
+// disable a particular flash block write
+//
+// Input: None
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+SpansionFlashBlockWriteDisable (
+ IN UINT8* pBlockAddress
+)
+{
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SpansionFlashDeviceWriteEnable
+//
+// Description: This function contains any flash specific code need to
+// enable flash write
+//
+// Input: None
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+SpansionFlashDeviceWriteEnable (VOID)
+{
+ //We don't have to do anything here because
+ //Flash Device is write enabled by the South Bridge driver
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SpansionFlashDeviceWriteDisable
+//
+// Description: This function contains any flash specific code need to
+// disable flash write
+//
+// Input: None
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID
+SpansionFlashDeviceWriteDisable (VOID)
+{
+ //We don't have to do anything here because
+ //we always keep flash device in the write enabled state
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SpansionFlashVirtualFixup
+//
+// Description: This function will be invoked by the core to convert
+// runtime pointers to virtual address
+//
+// Input: *pRS Pointer to runtime services
+//
+// Output: None
+//
+// Return: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static
+VOID
+SpansionFlashVirtualFixup(
+ IN EFI_RUNTIME_SERVICES *pRS
+)
+{
+
+// // Following is an example code for virtual address conversion
+// pRS->ConvertPointer(0, (VOID**)&FlashDeviceBase);
+
+ return;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: mStdSpansionIdentify
+//
+// Description: This function identifies the supported Spansion flash part and
+// returns appropriate flash device API pointer. If flash part is
+// not supported by this module it will return FALSE.
+//
+//
+// Input: pBlockAddress Block address of the flash part. Can be used to
+// send ID command
+//
+// Output: **FlashApi Pointer to hold the returned flash API
+//
+// Return: TRUE If flash part is supported, FlashApi contains
+// routines to handle the flash requests
+// FALSE Flash part is not supported
+//
+// Note: This routine is part of the global flash init list. Make sure
+// it is properly linked to the init list "FlashList" (in SDL file)
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN
+mStdSpansionIdentify (
+ IN volatile UINT8* pBlockAddress,
+ OUT FLASH_PART **Struct
+)
+{
+ UINT8 MID;
+ UINT8 DID1, DID2, DID3;
+
+ SpansionResetFlash( pBlockAddress );
+
+ pBlockAddress[0xaaa] = 0xaa;
+ pBlockAddress[0x555] = 0x55;
+ pBlockAddress[0xaaa] = 0x90;
+ // Delay before read flash ID.
+ IoWrite8 ( 0xeb, 0x55 );
+ MID = *pBlockAddress;
+ DID1 = *(pBlockAddress + 0x02);
+ DID2 = *(pBlockAddress + 0x1c);
+ DID3 = *(pBlockAddress + 0x1e);
+
+ SpansionResetFlash( pBlockAddress );
+
+ // Check MID & DID1 for S29GL01G/512/256/128P support.
+ if ((MID == S29GL01GP_MANID) && (DID1 == S29GL01GP_DEVID1)) {
+ MemCpy ( pFlashDeviceNumber, "Spansion S29GL128/256/512/01GP", 30 );
+ mStdSpansionFlash.FlashPartNumber = pFlashDeviceNumber;
+ *Struct = &mStdSpansionFlash;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************