summaryrefslogtreecommitdiff
path: root/Core/EM/Runtime
diff options
context:
space:
mode:
authorraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
committerraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
commitb7c51c9cf4864df6aabb99a1ae843becd577237c (patch)
treeeebe9b0d0ca03062955223097e57da84dd618b9a /Core/EM/Runtime
downloadzprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'Core/EM/Runtime')
-rw-r--r--Core/EM/Runtime/CpuIoDxe.c547
-rw-r--r--Core/EM/Runtime/Flash.c1014
-rw-r--r--Core/EM/Runtime/Runtime.c579
-rw-r--r--Core/EM/Runtime/Runtime.cif10
-rw-r--r--Core/EM/Runtime/Runtime.dxs49
-rw-r--r--Core/EM/Runtime/Runtime.mak102
-rw-r--r--Core/EM/Runtime/Runtime.sdl129
-rw-r--r--Core/EM/Runtime/RuntimeSrc.cif13
-rw-r--r--Core/EM/Runtime/RuntimeSrc.mak74
-rw-r--r--Core/EM/Runtime/RuntimeSrc.sdl57
-rw-r--r--Core/EM/Runtime/TimeAndReset.C1191
11 files changed, 3765 insertions, 0 deletions
diff --git a/Core/EM/Runtime/CpuIoDxe.c b/Core/EM/Runtime/CpuIoDxe.c
new file mode 100644
index 0000000..e542418
--- /dev/null
+++ b/Core/EM/Runtime/CpuIoDxe.c
@@ -0,0 +1,547 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/Runtime/CpuIoDxe.c 5 5/17/12 4:14p Artems $
+//
+// $Revision: 5 $
+//
+// $Date: 5/17/12 4:14p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/Runtime/CpuIoDxe.c $
+//
+// 5 5/17/12 4:14p Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Added support to address MMIO space above 4GB in x64
+// mode
+// [Files] CpuIoDxe.c
+//
+// 4 4/15/11 12:47p Artems
+// EIP 56523: Added support of PI specification v 1.2
+//
+// 3 6/24/09 4:24p Robert
+// updated Comments, copyrights, and some coding standard issues
+//
+// 2 10/21/08 3:41p Felixp
+// Support for usage of the protocol at runtime is added.
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: CpuIo.c
+//
+// Description:
+// This file contains Protocol functions and definitions for the
+// EFI_CPU_IO_PROTOCOL. This protocol contains functions for memory and I/O
+// access
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+//==========================================================================
+// Includes
+#include <Protocol\CpuIo.h>
+#include <AmiDxeLib.h>
+
+
+//==========================================================================
+// GUID definitions
+
+//==========================================================================
+// Function Definitions
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CpuIoMemRead
+//
+// Description:
+// This function reads from the Memory space at the address defined by Address
+// with the size defined by the lowest 2 bits in the Width parameter. It
+// repeats this Count number of times while incrementing the Buffer,
+// the Address, or both depending on the type of operation defined by the
+// upper 6 bits in the width parameter. Refer to the notes section for
+// further definition of the Width parameter
+//
+// Input:
+// IN EFI_CPU_IO_PROTOCOL *This - Pointer to the EFI_CPU_IO_PROTOCOL
+// IN EFI_CPU_IO_PROTOCOL_WIDTH Width - Contains Type and Width of the Memory operation
+// IN UINT64 Address - Memory address to read from
+// IN UINTN Count - number of times to perform the read operation
+// IN OUT VOID *Buffer - Data buffer to store the data read
+//
+// Output:
+// EFI_SUCCESS
+//
+// Notes:
+// The Width Variable contains a width and a type component
+// - The width is defined by the lowest 2 bits
+// - The Type is defined by the other bits as follows:
+// - - Type = 0 - EfiIoWidthUintxx - Increment Buffer and address
+// - - Type = 1 - EfiIoWidthFifoUintxx - Increment only Buffer
+// - - Type > 1 - EfiIoWidthFillUintxx - Increment only Address
+// - The increment happens after each Operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CpuIoMemRead(
+ IN EFI_CPU_IO_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+)
+{
+ UINTN IncrementType = Width & ~3;
+ UINT8 IncrementValue = 1 << (Width & 3); //1st 2 bits currently define width. Other bits define type.
+ UINT8 IncrementBuffer = 0;
+ UINT8 IncrementAddress = 0;
+ UINT64 Limit;
+
+ if (Buffer==NULL) return EFI_INVALID_PARAMETER;
+ if (IncrementType > 16 || IncrementValue > 8) return EFI_INVALID_PARAMETER;
+
+ Limit = (sizeof(UINTN) < 8) ? 0xffffffff : 0xffffffffffffffff;
+ if ((Count * IncrementValue) > (Limit - Address))
+ return EFI_INVALID_PARAMETER; //Memory must be within range of the bridge.
+
+ switch (IncrementType)
+ {
+ case 0: //EfiIoWidthUintxx
+ IncrementAddress = IncrementBuffer = IncrementValue;
+ break;
+ case 4: //EfiIoWidthFifoUintxx
+ IncrementBuffer = IncrementValue;
+ break;
+ default: //EfiIoWidthFillUintxx
+ IncrementAddress = IncrementValue;
+ }
+
+ while(Count--)
+ {
+ switch(IncrementValue)
+ {
+ case 1: // byte
+ *(UINT8*) Buffer = *(UINT8*)Address;
+ break;
+ case 2: // word
+ *(UINT16*) Buffer = *(UINT16*)Address;
+ break;
+ case 4: // dword
+ *(UINT32*) Buffer = *(UINT32*)Address;
+ break;
+ case 8: // qword
+ *(UINT64*) Buffer = *(UINT64*)Address;
+ break;
+ default: return EFI_INVALID_PARAMETER;
+ }
+ (UINT8*) Buffer += IncrementBuffer;
+ Address += IncrementAddress;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CpuIoMemWrite
+//
+// Description:
+// This function writes to the Memory space at the address defined by Address
+// with the size defined by the lowest 2 bits in the Width parameter. It
+// repeats this Count number of times while incrementing the Buffer,
+// the Address, or both depending on the type of operation defined by the
+// upper 6 bits in the width parameter. Refer to the notes section for
+// further definition of the Width parameter
+//
+// Input:
+// IN EFI_CPU_IO_PROTOCOL *This - Pointer to the EFI_CPU_IO_PROTOCOL
+// IN EFI_CPU_IO_PROTOCOL_WIDTH Width - Contains Type and Width of the Memory operation
+// IN UINT64 Address - Memory address to Write to
+// IN UINTN Count - number of times to perform the write operation
+// IN OUT VOID *Buffer - Data buffer of the data to write
+//
+// Output:
+// EFI_SUCCESS
+//
+// Notes:
+// The Width Variable contains a width and a type component
+// - The width is defined by the lowest 2 bits
+// - The Type is defined by the other bits as follows:
+// - - Type = 0 - EfiIoWidthUintxx - Increment Buffer and address
+// - - Type = 1 - EfiIoWidthFifoUintxx - Increment only Buffer
+// - - Type > 1 - EfiIoWidthFillUintxx - Increment only Address
+// - The increment happens after each Operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CpuIoMemWrite(
+ IN EFI_CPU_IO_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+)
+{
+ // 1st 2 bits currently define width. Other bits define type.
+ UINTN IncrementType = Width & ~3;
+ UINT8 IncrementValue = 1 << (Width & 3);
+ UINT8 IncrementBuffer = 0;
+ UINT8 IncrementAddress = 0;
+ UINT64 Limit;
+
+ if (Buffer==NULL) return EFI_INVALID_PARAMETER;
+ if (IncrementType > 16 || IncrementValue > 8) return EFI_INVALID_PARAMETER;
+
+ // Memory must be within range of the bridge.
+ Limit = (sizeof(UINTN) < 8) ? 0xffffffff : 0xffffffffffffffff;
+ if ((Count * IncrementValue) > (Limit - Address))
+ return EFI_INVALID_PARAMETER;
+
+ switch (IncrementType)
+ {
+ case 0: //EfiIoWidthUintxx
+ IncrementAddress = IncrementBuffer = IncrementValue;
+ break;
+ case 4: //EfiIoWidthFifoUintxx
+ IncrementBuffer = IncrementValue;
+ break;
+ default: //EfiIoWidthFillUintxx
+ IncrementAddress = IncrementValue;
+ }
+
+ while(Count--)
+ {
+ switch(IncrementValue)
+ {
+ case 1: //byte
+ *(UINT8*) Address = *(UINT8*)Buffer;
+ break;
+ case 2: //word
+ *(UINT16*) Address = *(UINT16*)Buffer;
+ break;
+ case 4: //dword
+ *(UINT32*) Address = *(UINT32*)Buffer;
+ break;
+ case 8: // qword
+ *(UINT64*) Address = *(UINT64*)Buffer;
+ break;
+ default: return EFI_INVALID_PARAMETER;
+ }
+ (UINT8*) Buffer += IncrementBuffer;
+ Address += IncrementAddress;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CpuIoIoRead
+//
+// Description:
+// This function reads the IO space at the address defined by Address
+// with the size defined by the lowest 2 bits in the Width parameter. It
+// repeats this Count number of times while incrementing the Buffer,
+// the Address, or both depending on the type of operation defined by the
+// upper 6 bits in the width parameter. Refer to the notes section for
+// further definition of the Width parameter
+//
+// Input:
+// IN EFI_CPU_IO_PROTOCOL *This - Pointer to the EFI_CPU_IO_PROTOCOL
+// IN EFI_CPU_IO_PROTOCOL_WIDTH Width - Contains Type and Width of the Io operation
+// IN UINT64 Address - IO address to Read from
+// IN UINTN Count - number of times to perform the read operation
+// IN OUT VOID *Buffer - Data buffer to store the data read
+//
+// Output:
+// EFI_SUCCESS
+//
+// Notes:
+// The Width Variable contains a width and a type component
+// - The width is defined by the lowest 2 bits
+// - The Type is defined by the other bits as follows:
+// - - Type = 0 - EfiIoWidthUintxx - Increment Buffer and address
+// - - Type = 1 - EfiIoWidthFifoUintxx - Increment only Buffer
+// - - Type > 1 - EfiIoWidthFillUintxx - Increment only Address
+// - The increment happens after each Operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CpuIoIoRead(
+ IN EFI_CPU_IO_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+)
+{
+ //1st 2 bits of the Width parameter currently define width. Other bits define type.
+ UINTN IncrementType = Width & ~3;
+ UINT8 IncrementValue = 1 << (Width & 3);
+ UINT8 IncrementBuffer = 0;
+ UINT8 IncrementAddress = 0;
+
+ if ((UINT32) Width >= EfiCpuIoWidthMaximum) return EFI_INVALID_PARAMETER;
+
+ if (Buffer==NULL) return EFI_INVALID_PARAMETER;
+ if (IncrementType > 16 || IncrementValue > 8) return EFI_INVALID_PARAMETER;
+
+ if ((Address + Count * IncrementValue) > 0xffff)
+ return EFI_INVALID_PARAMETER; //Memory must be within range of the bridge.
+
+ switch (IncrementType)
+ {
+ case 0: //EfiIoWidthUintxx
+ IncrementAddress = IncrementBuffer = IncrementValue;
+ break;
+ case 4: //EfiIoWidthFifoUintxx
+ IncrementBuffer = IncrementValue;
+ break;
+ default: //EfiIoWidthFillUintxx
+ IncrementAddress = IncrementValue;
+ }
+
+ while(Count--)
+ {
+ switch(IncrementValue)
+ {
+ case 1: // byte
+ *(UINT8*) Buffer = IoRead8((UINT16)Address);
+ break;
+ case 2: // word
+ *(UINT16*) Buffer = IoRead16((UINT16)Address);
+ break;
+ case 4: // dword
+ *(UINT32*) Buffer = IoRead32((UINT16)Address);
+ break;
+ case 8: // qword
+ *(UINT32*) Buffer = IoRead32((UINT16)Address);
+ *((UINT32*)((UINT32*)Buffer+1)) = IoRead32((UINT16)(Address+4));
+ break;
+ default: return EFI_INVALID_PARAMETER;
+ }
+ (UINT8*) Buffer += IncrementBuffer;
+ Address += IncrementAddress;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CpuIoIoWrite
+//
+// Description:
+// This function writes to the IO space at the address defined by Address
+// with the size defined by the lowest 2 bits in the Width parameter. It
+// repeats this Count number of times while incrementing the Buffer,
+// the Address, or both depending on the type of operation defined by the
+// upper 6 bits in the width parameter. Refer to the notes section for
+// further definition of the Width parameter
+//
+// Input:
+// IN EFI_CPU_IO_PROTOCOL *This - Pointer to the EFI_CPU_IO_PROTOCOL
+// IN EFI_CPU_IO_PROTOCOL_WIDTH Width - Contains Type and Width of the Io operation
+// IN UINT64 Address - IO address to Write to
+// IN UINTN Count - number of times to perform the write operation
+// IN OUT VOID *Buffer - Data buffer of the data to write
+//
+// Output:
+// EFI_SUCCESS
+//
+// Notes:
+// The Width Variable contains a width and a type component
+// - The width is defined by the lowest 2 bits
+// - The Type is defined by the other bits as follows:
+// - - Type = 0 - EfiIoWidthUintxx - Increment Buffer and address
+// - - Type = 1 - EfiIoWidthFifoUintxx - Increment only Buffer
+// - - Type > 1 - EfiIoWidthFillUintxx - Increment only Address
+// - The increment happens after each Operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CpuIoIoWrite(
+ IN EFI_CPU_IO_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+)
+{
+ //1st 2 bits of the Width parameter currently define width. Other bits define type.
+ UINTN IncrementType = Width & ~3;
+ UINT8 IncrementValue = 1 << (Width & 3);
+ UINT8 IncrementBuffer = 0;
+ UINT8 IncrementAddress = 0;
+
+ if ((UINT32) Width >= EfiCpuIoWidthMaximum) return EFI_INVALID_PARAMETER;
+
+ if (Buffer==NULL) return EFI_INVALID_PARAMETER;
+ if (IncrementType > 16 || IncrementValue > 4) return EFI_INVALID_PARAMETER;
+
+ if ((Address + Count * IncrementValue) > 0xffff)
+ return EFI_INVALID_PARAMETER; //Memory must be within range of the bridge.
+
+ switch (IncrementType)
+ {
+ case 0: //EfiIoWidthUintxx
+ IncrementAddress = IncrementBuffer = IncrementValue;
+ break;
+ case 4: //EfiIoWidthFifoUintxx
+ IncrementBuffer = IncrementValue;
+ break;
+ default: //EfiIoWidthFillUintxx
+ IncrementAddress = IncrementValue;
+ }
+
+ while(Count--)
+ {
+ switch(IncrementValue)
+ {
+ case 1: //byte
+ IoWrite8((UINT16)Address,*(UINT8*) Buffer);
+ break;
+ case 2: //word
+ IoWrite16((UINT16)Address,*(UINT16*) Buffer);
+ break;
+ default: //dword
+ IoWrite32((UINT16)Address,*(UINT32*) Buffer);
+ break;
+ }
+ (UINT8*) Buffer += IncrementBuffer;
+ Address += IncrementAddress;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+static EFI_CPU_IO_PROTOCOL gEfiCpuIoProtocol = {
+ { CpuIoMemRead, CpuIoMemWrite },
+ { CpuIoIoRead, CpuIoIoWrite },
+};
+
+//==========================================================================
+// Module specific Global Variable
+static EFI_RUNTIME_SERVICES *MyRS=NULL;
+// End Module specific Global Variable
+//==========================================================================
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CpuIoVirtAddressChange
+//
+// Description:
+// This function is a callback function that changes the Protocol function
+// pointers from Physical Address Mapping to Virtual Address Mapping
+//
+// Input:
+// IN EFI_EVENT Event - Pointer to the event that was triggered
+// IN VOID *Context - Buffer Pointer defined by the code that calls CreateEvent
+//
+// Output:
+// None
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID CpuIoVirtAddressChange (IN EFI_EVENT Event, IN VOID *Context)
+{
+ MyRS->ConvertPointer(0,(VOID**)&gEfiCpuIoProtocol.Mem.Read);
+ MyRS->ConvertPointer(0,(VOID**)&gEfiCpuIoProtocol.Mem.Write);
+ MyRS->ConvertPointer(0,(VOID**)&gEfiCpuIoProtocol.Io.Read);
+ MyRS->ConvertPointer(0,(VOID**)&gEfiCpuIoProtocol.Io.Write);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CpuIoDxeInit
+//
+// Description:
+// This function is the entry point for the EFI_CPU_IO_PROTOCOL.
+//
+// Input:
+// EFI_HANDLE ImageHandle - The firmware allocated handle for this driver
+// EFI_SYSTEM_TABLE *SystemTable - Pointer to the UEFI SystemTable
+//
+// Output:
+// EFI_SUCCESS
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CpuIoDxeInit(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable)
+{
+ EFI_HANDLE Handle = NULL;
+ EFI_STATUS Status;
+
+ // initialize the AMI Library
+ InitAmiLib(ImageHandle, SystemTable);
+
+ // install the CpuIo Protocol
+ Status = pBS->InstallMultipleProtocolInterfaces(
+ &Handle,
+ &gEfiCpuIoProtocolGuid, &gEfiCpuIoProtocol,
+#if PI_SPECIFICATION_VERSION >= 0x10014
+ &gEfiCpuIo2ProtocolGuid, &gEfiCpuIoProtocol,
+#endif
+ NULL);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status))
+ return Status;
+
+{
+ EFI_EVENT Event;
+ // defines the local Runtime Services pointer
+ MyRS = pRS;
+
+ // creates event for virtual address change fixup
+ Status = pBS->CreateEvent(
+ EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
+ TPL_CALLBACK,
+ &CpuIoVirtAddressChange,
+ NULL,
+ &Event);
+}
+
+ return Status;
+}
+
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
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
diff --git a/Core/EM/Runtime/Runtime.c b/Core/EM/Runtime/Runtime.c
new file mode 100644
index 0000000..cebe355
--- /dev/null
+++ b/Core/EM/Runtime/Runtime.c
@@ -0,0 +1,579 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (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/Core/Runtime/Runtime.c 23 6/16/11 9:07a Felixp $
+//
+// $Revision: 23 $
+//
+// $Date: 6/16/11 9:07a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/Runtime/Runtime.c $
+//
+// 23 6/16/11 9:07a Felixp
+// Enhancements(EIP 49676):
+// 1. FindDescriptor: upated to ignore boot time memory map descriptors
+// 2. SetVirtualAddressMap: updated to skip virtual address change
+// callbacks that reside in the boot time memory.
+//
+// 22 9/22/10 6:57p Felixp
+// Minor improvements: use InitAmiRuntimeLib instead of InitAmiLib
+//
+// 21 3/12/10 12:00p Felixp
+//
+// 20 3/12/10 10:26a Felixp
+// Bug fix: Potential problems with UEFI OS.
+// pST was used here even after it has been virtualized in the
+// AmiLibGoVirtual.
+// The local copy of the pointer is created.
+//
+// 19 7/08/09 12:00p Felixp
+//
+// 18 6/24/09 4:23p Robert
+// updated comments, copyright and some coding standard items
+//
+// 17 5/14/09 9:34a Felixp
+// New feature: SMM version of Runtime Services
+// Runtime driver is updated to install SMM version of the runtime
+// services table.
+//
+// 15 11/20/08 2:58p Felixp
+// Bug fix in SetVirtualAddressMap( bug fix in the runtime images fixup
+// logic )
+//
+// 14 11/07/07 11:54a Felixp
+// Bug fix in FindDescriptor routine
+//
+// 13 8/07/07 2:23p Felixp
+// New StatusCodes added
+//
+// 7 10/27/06 10:31a Felixp
+// checkpoints on begin/end of SetVirtualAddressMap added
+//
+// 6 10/27/06 10:15a Felixp
+// Bug fixes in SetVirtualAddressMap
+//
+// 5 10/07/06 10:22a Felixp
+// New Runtime protocol defined by DXE CIS 0.91 implemented
+// (Old(DXE CIS 0.90) Runtime protocol and AMI Runtime protocols removed).
+//
+// 3 1/18/05 3:22p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 14 12/23/04 9:29a Felixp
+// ArchProtocols moved to Include\Protocols
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Runtime.c
+//
+// Description:
+// This file contains the Runtime Architectural Protocol along with
+// some runtime functions that are included in the Runtime Services Table
+// SetVirtualAddressMap, ConvertPointer, and CalculateCrc32. The entry
+// point for the Runtime Driver also contains a call to InitParts which
+// uses the RuntimeInitialize and RuntimeSmmInitialize eLinks to
+// initialize other pieces of the Runtime Structure
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+//=============================================================================
+// Includes
+#include <Protocol/Runtime.h>
+#include <Protocol/LoadedImage.h>
+#include <AmiDxeLib.h>
+
+//=============================================================================
+// Protocol Definition
+EFI_RUNTIME_ARCH_PROTOCOL Runtime =
+{
+ {&Runtime.ImageHead,&Runtime.ImageHead}, //EFI_LIST_ENTRY ImageHead;
+ {&Runtime.EventHead,&Runtime.EventHead}, //EFI_LIST_ENTRY EventHead;
+ 0, //UINTN MemoryDescriptorSize;
+ 0, //UINT32 MemoryDesciptorVersion;
+ 0, //UINTN MemoryMapSize;
+ NULL, //EFI_MEMORY_DESCRIPTOR *MemoryMapPhysical;
+ NULL, //EFI_MEMORY_DESCRIPTOR *MemoryMapVirtual;
+ FALSE, //BOOLEAN VirtualMode;
+ FALSE //BOOLEAN AtRuntime;
+} ;
+
+
+//=============================================================================
+// Module specific Global Variables
+
+static EFI_MEMORY_DESCRIPTOR *pMap = NULL;
+static UINTN MapSize, DescSize;
+static UINT32 CrcTable[256];
+
+//=============================================================================
+// Function Prototypes
+
+//this funciton is created from InitList.c template file during build process
+VOID InitParts(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable);
+
+
+EFI_STATUS SetVirtualAddressMap(
+ IN UINTN MemoryMapSize, IN UINTN DescriptorSize,
+ IN UINT32 DescriptorVersion, IN EFI_MEMORY_DESCRIPTOR *VirtualMap
+);
+
+EFI_STATUS ConvertPointer(
+ IN UINTN DebugDisposition, IN VOID **Address
+);
+
+EFI_STATUS CalculateCrc32(
+ IN VOID *Data, IN UINTN DataSize, OUT UINT32 *Crc32
+);
+
+VOID InitCrc();
+
+//=============================================================================
+// Function Definitions
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: RuntimeInitialize
+//
+// Description:
+// This function is the Initialization function for the runtime driver that is
+// outside of SMM. It sets up all the pieces of the Runtime Architectural
+// Protocol that exist outside of SMM
+//
+// Input:
+// EFI_HANDLE ImageHandle - The firmware allocated handle for this driver
+// EFI_SYSTEM_TABLE *SystemTable - Pointer to the UEFI SystemTable
+//
+// Output:
+// EFI_SUCCESS
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS RuntimeInitialize(
+ IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_HANDLE Handle = NULL;
+
+ InitAmiRuntimeLib(ImageHandle, SystemTable, NULL, NULL);
+ InitCrc();
+
+ //this funciton is created from InitList.c template file during build process
+ InitParts(ImageHandle, SystemTable);
+
+ // Initialize pointers in the Runtime Services Table
+ pRS->SetVirtualAddressMap = SetVirtualAddressMap;
+ pRS->ConvertPointer = ConvertPointer;
+ pBS->CalculateCrc32 = CalculateCrc32;
+
+ // install the Runtime Achitectural Protocol
+ pBS->InstallMultipleProtocolInterfaces(
+ &Handle, &gEfiRuntimeArchProtocolGuid, &Runtime, NULL
+ );
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindDescriptor
+//
+// Description:
+// This function finds the memory descriptor that contains the pointer that
+// is passed into the function. This is used by the ConvertPointer function
+// to determine how to find the virtual fixup address of the pointer
+//
+// Input:
+// VOID *p - Pointer that needs to be fixed up
+//
+// Output:
+// EFI_MEMORY_DESCRIPTOR * - Memory descriptor that contain the pointer that is passed in
+//
+// Notes:
+// Used only by ConvertPointer function to help it convert the pointer from
+// a physical address to a virtual address
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_MEMORY_DESCRIPTOR* FindDescriptor(VOID *p)
+{
+ EFI_MEMORY_DESCRIPTOR *pD;
+ EFI_PHYSICAL_ADDRESS Address = (EFI_PHYSICAL_ADDRESS)(UINTN)p;
+
+ if(!pMap) return NULL;
+ // Search for the memory descriptor that contains the address of the pointer
+ // that was passed in
+ for(pD = pMap
+ ;pD < (EFI_MEMORY_DESCRIPTOR*)((UINT8*)pMap + MapSize)
+ ;pD = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)pD + DescSize)
+ ) if ( (pD->Attribute & EFI_MEMORY_RUNTIME)
+ && pD->PhysicalStart <= Address
+ && pD->PhysicalStart + Shl64(pD->NumberOfPages, EFI_PAGE_SHIFT)
+ > Address
+ ) return pD;
+ return NULL;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetVirtualAddressMap
+//
+// Description:
+// This function is called by a UEFI OS. It changes the pointers for the
+// Runtime Services Table and each of the function pointers and variables
+// that are its elements from physical addresses to virtual addresses.
+//
+// Input:
+// IN UINTN MemoryMapSize - Size of the Current Memory Map
+// IN UINTN DescriptorSize - Size of one descriptor in the Memory Map
+// IN UINT32 DescriptorVersion - Version of the MemoryDescriptor Data Structure
+// IN EFI_MEMORY_DESCRIPTOR *VirtualMap - Address to the first Descriptor in the Virtual Memory Map
+//
+// Output:
+// EFI_SUCCESS
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS SetVirtualAddressMap(
+ IN UINTN MemoryMapSize,
+ IN UINTN DescriptorSize,
+ IN UINT32 DescriptorVersion,
+ IN EFI_MEMORY_DESCRIPTOR *VirtualMap
+)
+{
+ EFI_LIST_ENTRY *pLink;
+ VOID **p;
+ UINTN i;
+ UINT32 crc;
+ EFI_RUNTIME_IMAGE_ENTRY *pThisImageEntry;
+ VOID *VirtualImageBase;
+
+ //Make a local copy of pRS or pST
+ //it case one of the runtime drivers linked with this module
+ //converts pRS or pST to virtual address in the event handler
+ EFI_SYSTEM_TABLE *pSTCopy = pST;
+ EFI_RUNTIME_SERVICES *pRSCopy = pRS;
+
+ //SetVirtualAddressMap can only be called once
+ if(pMap) return EFI_UNSUPPORTED;
+ checkpoint(0xB0);
+
+ //Initialize Global Variables
+ pMap = VirtualMap;
+ MapSize = MemoryMapSize;
+ DescSize = DescriptorSize;
+
+ //Call Event notification funcitons
+ for(pLink = Runtime.EventHead.ForwardLink; pLink != &Runtime.EventHead; pLink = pLink->ForwardLink)
+ {
+ EFI_RUNTIME_EVENT_ENTRY *pEvent = OUTTER(pLink, Link, EFI_RUNTIME_EVENT_ENTRY);
+ if (!pEvent->NotifyFunction) continue;
+ //Let's see if the notification function we about to call is a runtime function
+ if (!FindDescriptor(pEvent->NotifyFunction)){
+ TRACE((TRACE_DXE_CORE,"ERROR: Virtual address change callback at address %X resides in the boot time memory\n",pEvent->NotifyFunction));
+ ASSERT(FALSE);
+ continue;
+ }
+ ASSERT(!pEvent->NotifyContext || FindDescriptor(pEvent->NotifyFunction));
+ pEvent->NotifyFunction(*pEvent->Event, pEvent->NotifyContext);
+ }
+
+ //Fixup runtime images
+ for(pLink = Runtime.ImageHead.ForwardLink; pLink != &Runtime.ImageHead; pLink = pLink->ForwardLink)
+ {
+ EFI_RUNTIME_IMAGE_ENTRY *pImage = OUTTER(pLink, Link, EFI_RUNTIME_IMAGE_ENTRY);
+ //skip this image; it will be fixed up later
+ if (TheImageHandle == pImage->Handle){
+ pThisImageEntry = pImage;
+ continue;
+ }
+ VirtualImageBase = pImage->ImageBase;
+ ConvertPointer(0, &VirtualImageBase);
+ ReallocatePeImage(pImage->ImageBase, VirtualImageBase, pImage->RelocationData);
+ }
+ //Fixup RuntimeServices
+ for(p = (VOID**)((UINT8*)pRSCopy + sizeof(pRSCopy->Hdr)); p < (VOID**)(pRSCopy + 1); p++)
+ ConvertPointer(0, p);
+ //Fixup Configuration Table
+ for(i = 0; i < pSTCopy->NumberOfTableEntries; i++)
+ ConvertPointer(0, &pSTCopy->ConfigurationTable[i].VendorTable);
+ //Fixup SystemTable
+ ConvertPointer(0, &pSTCopy->ConfigurationTable);
+ ConvertPointer(0, &pSTCopy->RuntimeServices);
+ ConvertPointer(0, &pSTCopy->FirmwareVendor);
+ // Update CRC32 of the System Tables
+ pRSCopy->Hdr.CRC32 = 0; crc = 0;
+ CalculateCrc32(pRSCopy, sizeof(*pRSCopy), &crc);
+ pRSCopy->Hdr.CRC32 = crc;
+ pSTCopy->Hdr.CRC32 = 0; crc = 0;
+ CalculateCrc32(pSTCopy, sizeof(*pSTCopy), &crc);
+ pSTCopy->Hdr.CRC32 = crc;
+
+ //finally, fixup ourself
+ VirtualImageBase = pThisImageEntry->ImageBase;
+ ConvertPointer(0, &VirtualImageBase);
+ ReallocatePeImage(pThisImageEntry->ImageBase, VirtualImageBase, pThisImageEntry->RelocationData);
+
+ checkpoint(0xB1);
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConvertPointer
+//
+// Description:
+// This function converts pointers from a Physical Memory Map Pointer
+// to a Virtual Memory Map Pointer. Called during the SetVirtualAddressMap
+// function execution.
+//
+// Input:
+// IN UINTN DebugDisposition - If set as EFI_OPTIONAL_POINTER, then Address is allowed to be NULL
+// IN VOID **Address - Pointer to convert to a virtual address
+//
+// Output:
+// EFI_SUCCESS - Pointer converted to Virtual Address
+// EFI_INVALID_PARAMETER - DebugDisposition != EFI_OPTIONAL_POINTER and *Address == NULL
+// EFI_INVALID_PARAMETER - Address == NULL
+// EFI_UNSUPPORTED - Virtual Memory Map address has not be set
+// EFI_NOT_FOUND - Descriptor not found that contains the address of *Address
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ConvertPointer(
+ IN UINTN DebugDisposition,
+ IN VOID **Address
+)
+{
+ EFI_MEMORY_DESCRIPTOR *pD;
+
+ // Check for error conditions
+ if(!pMap) return EFI_UNSUPPORTED;
+ if (!Address) return EFI_INVALID_PARAMETER;
+ if (!*Address)
+ return (DebugDisposition == EFI_OPTIONAL_PTR) ? EFI_SUCCESS : EFI_INVALID_PARAMETER;
+
+ // find the descriptor that contains the address passed in If not found, return error
+ if (!(pD = FindDescriptor(*Address))) return EFI_NOT_FOUND;
+
+ // if the descriptor is found, fixup the address to the new virtual address
+ *Address = (VOID*)((EFI_PHYSICAL_ADDRESS)*Address - pD->PhysicalStart + pD->VirtualStart);
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InitCrc
+//
+// Description:
+// This function Initializes the CrcTable with lookup values for future
+// use durning CRC32 calculations
+//
+// Input:
+// None
+//
+// Output:
+// None
+//
+// Notes:
+// At the end of this function the CrcTable will be initialized with lookup
+// values that make calculating CRC32 values much easier
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID InitCrc( VOID )
+{
+ UINT32 i;
+ UINT32 j;
+
+ for(i = 0; i < 256; i++)
+ {
+ CrcTable[i] = i;
+ for(j = 8; j > 0; j--)
+ CrcTable[i] = (CrcTable[i] & 1)
+ ? (CrcTable[i] >> 1)^0xedb88320
+ : CrcTable[i] >> 1;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CalculateCrc32
+//
+// Description:
+// This function Calculates a CRC32 value using the Data Buffer that is
+// and the DataSize passed in
+//
+// Input:
+// IN VOID *Data - Pointer to the data to have the CRC function run on
+// IN UINTN DataSize - Size in bytes of the Data pointed to by *Data
+//
+// Output:
+// OUT UINT32 *Crc32 - CRC32 value calculated based on Data and Data Size
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CalculateCrc32(
+ IN VOID *Data, IN UINTN DataSize, OUT UINT32 *Crc32
+)
+{
+ UINT32 i, crc = (UINT32)-1;
+ if (!Data || !DataSize || !Crc32) return EFI_INVALID_PARAMETER;
+ for(i = 0; i < DataSize; i++) crc = (crc >> 8)^CrcTable[(UINT8)crc^((UINT8*)Data)[i]];
+ *Crc32 = ~crc;
+ return EFI_SUCCESS;
+}
+
+//**********************************************************************
+// RT SMM BEGIN
+//**********************************************************************
+//======================================================================
+// SMM externs
+extern EFI_GUID SmmRsTableGuid;
+
+//======================================================================
+// SMM Function Prototypes
+
+//this funciton is created from InitList.c template file during build process
+VOID InitParts2(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable);
+
+
+//======================================================================
+// SMM Function Definitions
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DummySmmRtFunction
+//
+// Description:
+// This function is a Dummy function that is used as a default function
+// for the SMM instance of the Runtime Services Table
+//
+// Input:
+// None
+//
+// Output:
+// EFI_UNSUPPORTED
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS DummySmmRtFunction(){ return EFI_UNSUPPORTED; }
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: RuntimeSmmInitialize
+//
+// Description:
+// This function initializes the SMM version of the Runtime Services Table
+//
+// Input:
+// EFI_HANDLE ImageHandle - The firmware allocated handle for this driver
+// EFI_SYSTEM_TABLE *SystemTable - Pointer to the UEFI SystemTable
+//
+// Output:
+// EFI_STATUS - based on the return values of the SmmInstallConfigurationTable function
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS RuntimeSmmInitialize(
+ EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_RUNTIME_SERVICES SmmRs;
+ EFI_STATUS Status;
+ VOID **p;
+
+ //copy header
+ SmmRs.Hdr = pRS->Hdr;
+ //Init Runtime Services function pointers with our dummy function
+ for(p = (VOID**)((UINT8*)&SmmRs + sizeof(SmmRs.Hdr)); p < (VOID**)(&SmmRs + 1); p++)
+ *p = DummySmmRtFunction;
+
+ // install the SMM version of the Runtime Services Table SMM Configuration Table
+ Status = pSmst->SmmInstallConfigurationTable(
+ pSmst, &SmmRsTableGuid, &SmmRs, sizeof(EFI_RUNTIME_SERVICES) );
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: RuntimeEntry
+//
+// Description:
+// This function is the entry point for the Runtime Driver. It initializes
+// the AMI Library and then it calls the Initialization functions for both
+// the SMM and NON-SMM versions of the Runtime Driver. It then calls the
+// InitParts2 function which calls the functions in the RuntimeSmmInitialize
+// eLink.
+//
+// Input:
+// EFI_HANDLE ImageHandle - The firmware allocated handle for this driver
+// EFI_SYSTEM_TABLE *SystemTable - Pointer to the UEFI SystemTable
+//
+// Output:
+// EFI_STATUS - based on the return values of the InitSmmHandlerEx function
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS RuntimeEntry (
+ IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_STATUS Status;
+
+ // Initialize the AMI Library for this module
+ InitAmiLib(ImageHandle, SystemTable);
+
+ // Initialize both the SMM and Non-SMM verions of the Runtime Services
+ Status = InitSmmHandlerEx(
+ ImageHandle, SystemTable, RuntimeSmmInitialize, RuntimeInitialize
+ );
+ InitParts2(ImageHandle, SystemTable);
+ return Status;
+}
+//**********************************************************************
+// RT SMM 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/Core/EM/Runtime/Runtime.cif b/Core/EM/Runtime/Runtime.cif
new file mode 100644
index 0000000..d70f08f
--- /dev/null
+++ b/Core/EM/Runtime/Runtime.cif
@@ -0,0 +1,10 @@
+<component>
+ name = "Runtime"
+ category = ModulePart
+ LocalRoot = "Core\EM\Runtime\"
+ RefName = "Runtime"
+[files]
+"Runtime.sdl"
+"Runtime.mak"
+"Runtime.dxs"
+<endComponent>
diff --git a/Core/EM/Runtime/Runtime.dxs b/Core/EM/Runtime/Runtime.dxs
new file mode 100644
index 0000000..7e0cd64
--- /dev/null
+++ b/Core/EM/Runtime/Runtime.dxs
@@ -0,0 +1,49 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2004, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: $
+//
+// $Revision: $
+//
+// $Date: $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: $
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Runtime.dxs
+//
+// Description: Dependancy expression for the Runtime component
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+DEPENDENCY_START
+ TRUE
+DEPENDENCY_END
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2004, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/Runtime/Runtime.mak b/Core/EM/Runtime/Runtime.mak
new file mode 100644
index 0000000..6016f77
--- /dev/null
+++ b/Core/EM/Runtime/Runtime.mak
@@ -0,0 +1,102 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2009, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+
+#**********************************************************************
+# $Header: /Alaska/BIN/Core/Runtime/Runtime.mak 8 6/24/09 4:28p Robert $
+#
+# $Revision: 8 $
+#
+# $Date: 6/24/09 4:28p $
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/BIN/Core/Runtime/Runtime.mak $
+#
+# 8 6/24/09 4:28p Robert
+# updated file description
+#
+# 7 5/14/09 9:38a Felixp
+# New feature: SMM version of Runtime Services
+# Runtime driver is updated to install SMM version of the runtime
+# services table.
+# NVRAM driver is updated to populate SMM runtime table
+# with the pointers to SMM version of variable services.
+#
+# 6 5/01/09 6:11p Felixp
+# Bug fix(EIP 19816). $(AMICSPLib) is linked with Runtime module
+# (Used to be linked with NVRAM library that caused problems on systems
+# without Core Sources).
+#
+# 5 8/24/06 9:17a Felixp
+# Preliminary x64 support (work in progress)
+#
+# 4 12/02/05 11:16a Felixp
+# @set INCLUDE=%%INCLUDE%% removed since it's not needed.
+#
+# 3 6/16/05 10:48a Felixp
+# NVRAMTokens.c replaced with Tokens.c
+#
+# 2 2/11/05 5:48p Felixp
+# Binary files organization improved:
+# - extra layer of sub-component removed
+# - macros initialization moved to SDL tokens to eliminate undefined
+# macros situation
+# - debug and release binaries have different names now (workaround for
+# VeB limitation)
+# - binaries reside in the component home directory (eliminates
+# hardcoded paths)
+#
+# 3 1/18/05 3:22p Felixp
+# PrintDebugMessage renamed to Trace
+#
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: Runtime.mak
+#
+# Description:
+# This file contains the build commands for the Runtime binary
+# components.
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+all : RUNTIME
+
+RUNTIME : CORE_PEI $(BUILD_DIR)\RUNTIME.mak RUNTIMEBin
+
+$(BUILD_DIR)\RUNTIME.mak : $(RUNTIME_DIR)\$(@B).cif $(RUNTIME_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(RUNTIME_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+RUNTIMEBin : $(AMIDXELIB) $(Runtime_LIB) $(FLASHLIB) $(AMICSPLib)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\RUNTIME.mak all\
+ GUID=CBC59C4A-383A-41eb-A8EE-4498AEA567E4 \
+ ENTRY_POINT=RuntimeEntry \
+ TYPE=RT_DRIVER LIBRARIES= \
+ COMPRESS=1\
+ "INIT_LIST=$(RuntimeInitialize)"\
+ "INIT_LIST2=$(RuntimeSmmInitialize)"
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (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/Core/EM/Runtime/Runtime.sdl b/Core/EM/Runtime/Runtime.sdl
new file mode 100644
index 0000000..93f01d1
--- /dev/null
+++ b/Core/EM/Runtime/Runtime.sdl
@@ -0,0 +1,129 @@
+TOKEN
+ Name = "Runtime_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable Runtime support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "RTC_RUNTIME_SERVICES_SUPPORT"
+ Value = "1"
+ Help = "If ON includes in project CORE implementation of RTC \services (from TimeAndReset.c). \Set to OFF to use stand alone RTC driver."
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "RESET_RUNTIME_SERVICES_SUPPORT"
+ Value = "1"
+ Help = "If ON includes in project CORE implementation of reset \services (from TimeAndReset.c). \Set to OFF to use stand alone reset driver."
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "NVRAM_MONOTONIC_COUNTER_SUPPORT"
+ Value = "1"
+ Help = "If ON includes in project CORE NVRAM-based implementation of \the monotonic counter services.\Set to OFF to use stand alone monotonic counter driver."
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "NVRAM_RECORD_CHECKSUM_SUPPORT"
+ Value = "0"
+ Help = "When this token is enabled, every NVRAM record is checksummed."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "NVRAM_RT_GARBAGE_COLLECTION_SUPPORT"
+ Value = "1"
+ Help = "This token enables/disables support of the NVRAM garbage collection at runtime."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "NO_MMIO_FLASH_ACCESS_DURING_UPDATE"
+ Value = "0"
+ Help = "This token should be set to 1 if flash part is not memory mapped while write enabled."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+PATH
+ Name = "RUNTIME_DIR"
+End
+
+MODULE
+ Help = "Includes Runtime.mak to Project"
+ File = "Runtime.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\Runtime.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "RuntimeInitialize"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "Runtime_LIB"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "$(RUNTIME_DIR)\Runtime$(ARCH).lib"
+ Parent = "Runtime_LIB"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "CpuIoDxeInit,"
+ Parent = "RuntimeInitialize"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "RuntimeSmmInitialize"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "FlashDriverEntry,"
+ Parent = "RuntimeSmmInitialize"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "TimeServInit,"
+ Parent = "RuntimeSmmInitialize"
+ Token = "RTC_RUNTIME_SERVICES_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ResetServInit,"
+ Parent = "RuntimeSmmInitialize"
+ Token = "RESET_RUNTIME_SERVICES_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "NvRamSmmEntry,"
+ Parent = "FlashDriverEntry,"
+ InvokeOrder = AfterParent
+End
+
diff --git a/Core/EM/Runtime/RuntimeSrc.cif b/Core/EM/Runtime/RuntimeSrc.cif
new file mode 100644
index 0000000..020e79a
--- /dev/null
+++ b/Core/EM/Runtime/RuntimeSrc.cif
@@ -0,0 +1,13 @@
+<component>
+ name = "Runtime Sources"
+ category = ModulePart
+ LocalRoot = "Core\em\Runtime\"
+ RefName = "RuntimeSrc"
+[files]
+"RuntimeSrc.sdl"
+"RuntimeSrc.mak"
+"Runtime.c"
+"CpuIoDxe.c"
+"Flash.c"
+"TimeAndReset.C"
+<endComponent>
diff --git a/Core/EM/Runtime/RuntimeSrc.mak b/Core/EM/Runtime/RuntimeSrc.mak
new file mode 100644
index 0000000..1ee91a0
--- /dev/null
+++ b/Core/EM/Runtime/RuntimeSrc.mak
@@ -0,0 +1,74 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (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/Core/Runtime/RuntimeSrc.mak 5 6/24/09 4:22p Robert $
+#
+# $Revision: 5 $
+#
+# $Date: 6/24/09 4:22p $
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Core/Runtime/RuntimeSrc.mak $
+#
+# 5 6/24/09 4:22p Robert
+# Updated copyright and file description
+#
+# 4 8/24/06 9:28a Felixp
+# NVRAM removed (separate NVRAM component is created)
+#
+# 3 12/02/05 11:20a Felixp
+#
+# 2 8/23/05 12:02p Felixp
+# dependency from Token.h in debug mode added
+#
+# 1 1/28/05 12:45p Felixp
+#
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: RuntimeSrc.mak
+#
+# Description:
+# This file contains the build commands to create the Runtime Library
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+all : Runtime_LIB
+
+$(Runtime_LIB) : Runtime_LIB
+
+Runtime_LIB : $(BUILD_DIR)\RuntimeSrc.mak Runtime_LIBBin
+
+$(BUILD_DIR)\RuntimeSrc.mak : $(RUNTIME_DIR)\$(@B).cif $(RUNTIME_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(RUNTIME_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+Runtime_LIBBin :
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\RuntimeSrc.mak all\
+ TYPE=LIBRARY LIBRARY_NAME=$(Runtime_LIB)
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (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/Core/EM/Runtime/RuntimeSrc.sdl b/Core/EM/Runtime/RuntimeSrc.sdl
new file mode 100644
index 0000000..546f756
--- /dev/null
+++ b/Core/EM/Runtime/RuntimeSrc.sdl
@@ -0,0 +1,57 @@
+TOKEN
+ Name = "RuntimeSrc_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable RuntimeSrc support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "MINIMUM_YEAR"
+ Value = "1998"
+ Help = "Minimum allowed year.\If RTC year is less than this value, date will be reset to defaults."
+ TokenType = Integer
+ TargetH = Yes
+ Range = "1998"
+End
+
+TOKEN
+ Name = "DEFAULT_YEAR"
+ Value = "2009"
+ Help = "Default year. RTC will be reset to this value if current date is invalid."
+ TokenType = Integer
+ TargetH = Yes
+ Range = "MINIMUM_YEAR - 2099"
+End
+
+TOKEN
+ Name = "DEFAULT_MONTH"
+ Value = "1"
+ Help = "Default month. RTC will be reset to this value if current date is invalid."
+ TokenType = Integer
+ TargetH = Yes
+ Range = "1-12"
+End
+
+TOKEN
+ Name = "DEFAULT_DAY"
+ Value = "1"
+ Help = "Default day. RTC will be reset to this value if current date is invalid."
+ TokenType = Integer
+ TargetH = Yes
+ Range = "1-31"
+End
+
+MODULE
+ Help = "Includes RuntimeSrc.mak to Project"
+ File = "RuntimeSrc.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\Runtime.lib"
+ Parent = "$(RUNTIME_DIR)\Runtime$(ARCH).lib"
+ InvokeOrder = ReplaceParent
+End
+
diff --git a/Core/EM/Runtime/TimeAndReset.C b/Core/EM/Runtime/TimeAndReset.C
new file mode 100644
index 0000000..5e7ec77
--- /dev/null
+++ b/Core/EM/Runtime/TimeAndReset.C
@@ -0,0 +1,1191 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (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/Core/Runtime/TimeAndReset.C 10 11/17/10 4:44p Felixp $
+//
+// $Revision: 10 $
+//
+// $Date: 11/17/10 4:44p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/Runtime/TimeAndReset.C $
+//
+// 10 11/17/10 4:44p Felixp
+// Support for reset type override is added.
+//
+// 9 9/07/10 11:07p Felixp
+//
+// 8 9/02/10 4:49p Felixp
+// Enhancement: RTC driver is updated to use InitAmiRuntimeLib function.
+// The is safer that direct use of pRS->ConvertPointer since by the time
+// driver's
+// virtual address change callback is invoked, pRS may have already been
+// virtualized.
+//
+// 7 2/01/10 11:55a Felixp
+// Bug fix in EfiSetTime function. The timer zone variable was created
+// with the wrong size.
+//
+// 6 7/10/09 8:14a Felixp
+//
+// 4 6/24/09 4:25p Robert
+// updated comments, copyright and some coding standard issues
+//
+// 1 5/22/09 1:29p Felixp
+// RTC and Reset architectural protocols
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: TimeAndReset.C
+//
+// Description:
+// This file contains implementation of Time and Reset Runtime Services
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+//======================================================================
+// Module specific Includes
+#include <token.h>
+#include <AmiDxeLib.h>
+#include <AmiCspLib.h>
+
+//======================================================================
+// Produced Protocols
+#include <Protocol/Reset.h>
+#include <Protocol/RealTimeClock.h>
+#include <Protocol/Timer.h>
+
+/****************************** RTC Types and Constants *******************/
+//----------------------------------------------------------------------
+//Define Dallas DS12C887 Real Time Clock INDEX and DATA registers
+//----------------------------------------------------------------------
+#define RTC_INDEX_REG 0x70
+#define RTC_DATA_REG 0x71
+
+//----------------------------------------------------------------------
+//Define Internal Registers for Dallas DS12C887 Real Time Clock
+//----------------------------------------------------------------------
+#define RTC_SECONDS_REG 0x00 // R/W Range 0..59
+#define RTC_SECONDS_ALARM_REG 0x01 // R/W Range 0..59
+#define RTC_MINUTES_REG 0x02 // R/W Range 0..59
+#define RTC_MINUTES_ALARM_REG 0x03 // R/W Range 0..59
+#define RTC_HOURS_REG 0x04 // R/W Range 1..12
+ // or 0..23 Bit 7 is AM/PM
+#define RTC_HOURS_ALARM_REG 0x05 // R/W Range 1..12
+ // or 0..23 Bit 7 is AM/PM
+#define RTC_DAY_OF_WEEK_REG 0x06 // R/W Range 1..7
+#define RTC_DAY_OF_MONTH_REG 0x07 // R/W Range 1..31
+#define RTC_MONTH_REG 0x08 // R/W Range 1..12
+#define RTC_YEAR_REG 0x09 // R/W Range 0..99
+#define RTC_REG_A_INDEX 0x0a // R/W[0..6] R0[7]
+#define RTC_REG_B_INDEX 0x0b // R/W
+#define RTC_REG_C_INDEX 0x0c // RO
+#define RTC_REG_D_INDEX 0x0d // RO
+//Defined in ACPI.sdl
+//#define RTC_CENTURY_BYTE 50 // R/W Range 19..20 Bit 8 is R/W
+
+#define RTC_NMI_MASK 0x80
+
+#define AMI_RESET_TYPE_VARIABLE_GUID \
+ {0x308DD02C, 0x092B, 0x4123, 0xA2, 0xAF, 0x3E, 0xF4, 0x44, 0x0A, 0x6B, 0x4A}
+//----------------------------------------------------------------------
+//Registers A..D Bit definitions
+//----------------------------------------------------------------------
+#pragma pack(push,1)
+
+//----------------------------------------------------------------------
+// Register A
+//----------------------------------------------------------------------
+typedef union {
+ UINT8 REG_A;
+ struct {
+ UINT8 RateSel : 4;
+ UINT8 Divisor : 3;
+ UINT8 UpdInProgr : 1;
+ };
+} RTC_REG_A;
+
+//----------------------------------------------------------------------
+// Register B
+//----------------------------------------------------------------------
+typedef union {
+ UINT8 REG_B;
+ struct {
+ UINT8 DaylightSav : 1; // 0 - Daylight saving disabled
+ // 1 - Daylight savings enabled
+ UINT8 Mode : 1; // 0 - 12 hour mode
+ // 1 - 24 hour mode
+ UINT8 Format : 1; // 0 - BCD Format
+ // 1 - Binary Format
+ UINT8 SquareWave : 1; // 0 - Disable SQWE output
+ // 1 - Enable SQWE output
+ UINT8 UpdateInt : 1; // 0 - Update INT disabled
+ // 1 - Update INT enabled
+ UINT8 AlarmInt : 1; // 0 - Alarm INT disabled
+ // 1 - Alarm INT Enabled
+ UINT8 PeriodicInt : 1; // 0 - Periodic INT disabled
+ // 1 - Periodic INT Enabled
+ UINT8 Set : 1; // 0 - Normal operation.
+ // 1 - Updates inhibited
+ };
+} RTC_REG_B;
+
+//----------------------------------------------------------------------
+// Register C
+//----------------------------------------------------------------------
+typedef union {
+ UINT8 REG_C;
+ struct {
+ UINT8 Reserved : 4; // Read as zero. Can not be written.
+ UINT8 UpdEndFlag : 1; // Update End Interrupt Flag
+ UINT8 AlarmFlag : 1; // Alarm Interrupt Flag
+ UINT8 PeriodicFlag : 1; // Periodic Interrupt Flag
+ UINT8 IrqFlag : 1; // Iterrupt Request Flag =
+ // PF & PIE | AF & AIE | UF & UIE
+ };
+} RTC_REG_C;
+
+//----------------------------------------------------------------------
+// Register D
+//----------------------------------------------------------------------
+typedef union {
+ UINT8 REG_D;
+ struct {
+ UINT8 DateAlarm : 6;
+ UINT8 Reserved : 1; // Read as zero. Can not be written.
+ UINT8 DataValid : 1; // Valid RAM and Time
+ };
+} RTC_REG_D;
+
+#pragma pack(pop)
+/*********************** End of RTC Types and Constants *******************/
+
+
+//===========================================================================
+// Time Variable GUID Definition
+#define EFI_TIME_VARIABLE_GUID \
+ {0x9d0da369, 0x540b, 0x46f8, 0x85, 0xa0, 0x2b, 0x5f, 0x2c, 0x30, 0x1e, 0x15}
+
+//===========================================================================
+// Variable Declaration
+static BOOLEAN gTimeOut = FALSE;
+
+// GUID Definitions
+EFI_GUID gEfiTimeVariableGuid = EFI_TIME_VARIABLE_GUID;
+
+//This the number of days in a month - 1. (0 Based)
+UINT8 DaysInMonth[] = {30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30};
+
+//===========================================================================
+// UEFI Time Variable Type definition
+#pragma pack(1)
+typedef struct {
+ INT16 TimeZone;
+ UINT8 Daylight;
+ } TIME_VARIABLE;
+#pragma pack()
+
+//===========================================================================
+// Function Declarations
+VOID DummyFunction(IN EFI_EVENT Event, IN VOID *Context);
+
+//===========================================================================
+// Function Definitions
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: EfiResetSystem
+//
+// Description:
+// This function is the interface for the reset function.
+//
+// Input:
+// IN EFI_RESET_TYPE ResetType - Type of reset to perform
+// IN EFI_STATUS ResetStatus - System status that caused the reset. if part of normal operation
+// then this should be EFI_SUCCESS, Otherwise it should reflect the
+// state of the system that caused it
+// IN UINTN DataSize - Size in bytes of the data to be logged
+// IN CHAR16 *ResetData - Pointer to the data buffer that is to be logged - OPTIONAL
+//
+// Output:
+// EFI_DEVICE_ERROR - Even though it should never get that far
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+EfiResetSystem (
+ IN EFI_RESET_TYPE ResetType,
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN CHAR16 *ResetData OPTIONAL
+){
+ static EFI_GUID AmiResetTypeVariableGuid = AMI_RESET_TYPE_VARIABLE_GUID;
+ if (!EfiAtRuntime()){
+ EFI_EVENT Event;
+ UINT32 OverrideResetType;
+ UINTN Size = sizeof(UINT32);
+ EFI_STATUS Status;
+
+ pBS->CreateEventEx(
+ 0, TPL_CALLBACK, DummyFunction,
+ NULL, &AmiResetTypeVariableGuid, &Event
+ );
+ pBS->SignalEvent(Event);
+ pBS->CloseEvent(Event);
+ Status = pRS->GetVariable(
+ L"CspResetType", &AmiResetTypeVariableGuid, NULL,
+ &Size, &OverrideResetType
+ );
+ if (!EFI_ERROR(Status)) ResetType = OverrideResetType;
+ }
+ SBLib_ResetSystem (ResetType);
+ ASSERT(FALSE);
+ return EFI_DEVICE_ERROR;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DecToBCD
+//
+// Description:
+// This function converts data from DEC to BCD format
+//
+// Input:
+// UINT8 DEC - value to be converted
+//
+// Output:
+// UINT8 - result of conversion
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8 DecToBCD(UINT8 Dec)
+{
+ UINT8 FirstDigit = Dec % 10;
+ UINT8 SecondDigit = Dec / 10;
+
+ return (SecondDigit << 4) + FirstDigit;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BCDToDec
+//
+// Description:
+// This function converts data from BCD to DEC format
+//
+// Input:
+// UINT8 BCD - value to be converted
+//
+// Output:
+// UINT8 - result of conversion
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8 BCDToDec(UINT8 BCD)
+{
+ UINT8 FirstDigit = BCD & 0xf;
+ UINT8 SecondDigit = BCD >> 4;;
+
+ return SecondDigit * 10 + FirstDigit;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ReadRtcIndex
+//
+// Description:
+// Read the RTC value at the given Index.
+//
+// Input:
+// IN UINT8 Index - RTC Register Index to read from
+//
+// Output:
+// RTC Value read from the provided Index
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Read port 0x70 (RTC Index Register) to get bit 7.
+// Bit 7 is the NMI bit-it should not be changed.
+// 2. Set Index with the NMI bit setting.
+// 3. Output 0x70 with the Index.
+// 4. Read 0x71 for Data.
+// 5. Return the Data.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8 ReadRtcIndex(IN UINT8 Index)
+{
+ UINT8 NMI = IoRead8(RTC_INDEX_REG) & RTC_NMI_MASK; //Read bit 7 (NMI setting).
+ UINT8 volatile Value;
+ BOOLEAN IntState = CPULib_GetInterruptState();
+//----------------------
+ CPULib_DisableInterrupt();
+
+ IoWrite8(RTC_INDEX_REG, Index | NMI);
+ Value = IoRead8(RTC_DATA_REG); //Read register.
+
+ if (IntState) CPULib_EnableInterrupt();
+
+ if (Index <= RTC_YEAR_REG || Index == ACPI_CENTURY_CMOS) Value = BCDToDec(Value);
+
+ return (UINT8)Value;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: WriteRtcIndex
+//
+// Description:
+// Write the RTC value at the given Index.
+//
+// Input:
+// IN UINT8 Index - RTC register Index
+// IN UINT8 Value - Data to write to the Index indicated
+//
+// Output:
+// None
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Read port 0x70 (RTC Index Register) to get bit 7.
+// Bit 7 is the NMI bit-it should not be changed.
+// 2. Set Index with the NMI bit setting.
+// 3. Output 0x70 with the Index.
+// 4. Write the data to 0x71.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID WriteRtcIndex(IN UINT8 Index, IN UINT8 Value)
+{
+ UINT8 NMI = IoRead8(RTC_INDEX_REG) & RTC_NMI_MASK; //Read bit 7 (NMI setting).
+ BOOLEAN IntState=CPULib_GetInterruptState();
+//--------------------
+ if (Index <= RTC_YEAR_REG || Index == ACPI_CENTURY_CMOS) Value = DecToBCD(Value);
+
+ CPULib_DisableInterrupt();
+
+ IoWrite8(RTC_INDEX_REG,Index | NMI);
+ IoWrite8(RTC_DATA_REG, Value); //Write Register.
+
+ if (IntState) CPULib_EnableInterrupt();
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InitRtc
+//
+// Description:
+// This function initializes RTC
+//
+// Input:
+// None
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID InitRtc(VOID)
+{
+ WriteRtcIndex(RTC_REG_B_INDEX, 0x82);
+ WriteRtcIndex(RTC_REG_A_INDEX, 0x26);
+ ReadRtcIndex(RTC_REG_C_INDEX);
+ ReadRtcIndex(RTC_REG_D_INDEX);
+ WriteRtcIndex(RTC_REG_B_INDEX, 0x02);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetUpdate
+//
+// Description: Enables Disables RTC Date and Time update cicles.
+//
+// Input: Enable TRUE or FALSE to Enable\Disabe RTC Update.
+//
+// Output: NOTHING
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID SetUpdate(BOOLEAN Enable){
+ RTC_REG_B RegB;
+
+ RegB.REG_B = ReadRtcIndex(RTC_REG_B_INDEX);
+ if(RegB.Set == Enable) {
+ RegB.Set = !Enable;
+ WriteRtcIndex(RTC_REG_B_INDEX, RegB.REG_B);
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CheckUpdateCmplete
+//
+// Description:
+// Check if RTC Date and Time update in progress and waits till it's over.
+//
+// Input:
+// None
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID CheckUpdateCmplete(){
+ RTC_REG_A volatile RegA;
+ UINTN timeout=0;
+//-------------------------
+ RegA.REG_A = ReadRtcIndex(RTC_REG_A_INDEX);
+ while ( RegA.UpdInProgr){
+ RegA.REG_A = ReadRtcIndex(RTC_REG_A_INDEX);
+ timeout++;
+ if(timeout >= 0x0fffff){
+ gTimeOut = TRUE;
+ return;
+ }
+ }
+ gTimeOut=FALSE;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: VerifyTime
+//
+// Description: This routine verifies if time and data if needed, before
+// setting the RTC
+//
+// Input: *Time Time to verify with
+// CheckDate TRUE if check date also
+//
+// Output: TRUE if valid time and date
+//
+// Notes: Here is the control flow of this function:
+// 1. Decrease month and date to change to 0-base
+// 2. Validate Year, Month and Day. If invalid, return FALSE.
+// 3. Validate Hour, Minute, and Second. If invalid, return FALSE.
+// 4. Return True.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN VerifyTime(IN EFI_TIME *Time)
+{
+ //Always check these to satisfy EFI compliancy test even for setting wake-up time.
+ UINT8 Month = Time->Month - 1;
+ UINT8 Day = Time->Day - 1;
+
+ if (Time->Year < MINIMUM_YEAR || Time->Year > 2099) return FALSE;
+ if (Month > 11) return FALSE; //0 based month
+ if (Month != 1 || (Time->Year & 3)) { //not leap year or not February.
+ if (Day > DaysInMonth[Month]) return FALSE; //All values already adjusted for 0 based.
+ } else {
+ if (Day > 28) return FALSE; //February
+ }
+
+ if (Time->Hour > 23) return FALSE;
+ if (Time->Minute > 59) return FALSE;
+ if (Time->Second > 59) return FALSE;
+
+ //Check these to satisfy EFI compliancy test.
+ if (Time->Nanosecond > 999999999) return FALSE; //999,999,999
+ if (Time->TimeZone < -1440) return FALSE;
+ if (Time->TimeZone > 1440 && Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) return 0;
+
+ return TRUE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CheckRtc
+//
+// Description:
+// Check if RTC Mode and Format have appropriate values and sets them if
+// necessary
+//
+// Input:
+// BOOLEAN Set - if true, force Rtc to 24 hour mode and binary format
+//
+// Output:
+// EFI_SUCCESS - Rtc mode and format have appropriate values
+// EFI_DEVICE_ERROR - Rtc mode and/or format are invalid
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CheckRtc(BOOLEAN Set){
+ RTC_REG_B RegB;
+
+ //Check RTC Conditions and stuff
+ RegB.REG_B = ReadRtcIndex(RTC_REG_B_INDEX);
+ if(RegB.Mode == 0 || RegB.Format == 1) {
+ if(Set){
+ RegB.Mode = 1; // 0 - 12 hour mode 1 - 24 hour mode
+ RegB.Format = 0; // 0 - BCD Format 1 - Binary Format
+ WriteRtcIndex(RTC_REG_B_INDEX, RegB.REG_B);
+ } else {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: EfiGetTime
+//
+// Description:
+// Return the current date and time
+//
+// Input:
+// OUT EFI_TIME *Time - Current time filled in EFI_TIME structure
+// OUT EFI_TIME_CAPABILITIES *Capabilities - Time capabilities (OPTIONAL)
+//
+// Output:
+// EFI_SUCCESS Always
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Read the original time format 12/24 hours and BCD/binary.
+// 2. Set the format to 24 hrs and binary.
+// 3. Read the 2 digit year.
+// 4. Add either 1900 or 2000, so the year is between 1998 - 2097.
+// 5. Read the month, day, hour, minute, second.
+// 6. Set the nanosecond to 0.
+// 7. Set the time to zone to unspecified.
+// 8. Set daylight savings value to 0.
+// 9. Restore the original time format.
+// 10. Set Capabilities with 1 sec Resolution, 0 Accuracy (Unknown), and False SetsToZero.
+// 11. Return EFI_SUCCESS.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS EfiGetTime (
+ OUT EFI_TIME *Time,
+ OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL
+)
+{
+ EFI_STATUS Status;
+ UINT8 Year;
+ BOOLEAN IntState, SmiState;
+ UINTN TimeVarSize = sizeof(TIME_VARIABLE);
+ TIME_VARIABLE TimeVar;
+
+ if (Time == NULL) return EFI_INVALID_PARAMETER;
+ //Check RTC Conditions (24h Mode and BCD is ON)
+ Status = CheckRtc(FALSE);
+ if(EFI_ERROR(Status)) return Status;
+ //Get SMI State and disable it
+ SmiState = SbLib_GetSmiState();
+ SbLib_SmiDisable();
+ //Get INTERRUPT State and disable it
+ IntState = CPULib_GetInterruptState();
+ CPULib_DisableInterrupt();
+ // Wait till RTC is safe to read,
+ CheckUpdateCmplete();
+ if(gTimeOut){
+ InitRtc();
+ }
+
+ // After control comes back, we will have 488 u's to read data.
+ Year = ReadRtcIndex(RTC_YEAR_REG);
+ Time->Month = ReadRtcIndex(RTC_MONTH_REG);
+ Time->Day = ReadRtcIndex(RTC_DAY_OF_MONTH_REG);
+ Time->Hour = ReadRtcIndex(RTC_HOURS_REG);
+ Time->Minute = ReadRtcIndex(RTC_MINUTES_REG);
+ Time->Second = ReadRtcIndex(RTC_SECONDS_REG);
+ //Restore SMIs and INTERRUPT State
+ if(IntState) CPULib_EnableInterrupt();
+ if(SmiState) SbLib_SmiEnable();
+
+ //This Register is not affected by UIP bit so read it very last.
+ // If RTC Year only 1 digit, EFI spec says years rang is 1998 - 2097
+ Time->Year = ReadRtcIndex(ACPI_CENTURY_CMOS) * 100 + Year;
+ Time->Nanosecond= 0;
+
+ Status = pRS->GetVariable(
+ L"EfiTime",
+ &gEfiTimeVariableGuid,
+ NULL,
+ &TimeVarSize,
+ &TimeVar
+ );
+
+ if (EFI_ERROR(Status))
+ {
+ Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;
+ Time->Daylight = 0;
+ }
+ else
+ {
+ Time->TimeZone = TimeVar.TimeZone;
+ Time->Daylight = TimeVar.Daylight;
+ }
+
+ if (Capabilities != NULL) {
+ Capabilities->Resolution = 1;
+ Capabilities->Accuracy = 0;
+ Capabilities->SetsToZero = 0;
+ }
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: EfiSetTime
+//
+// Description:
+// Sets the RTC time
+//
+// Input:
+// IN EFI_TIME *Time - Time to set
+//
+// Output:
+// EFI_SUCCESS - Time is Set
+// EFI_INVALID_PARAMETER - Time to Set is not valid.
+//
+// Modified:
+// gTimeZone
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Read the original time format 12/24 hours and BCD/binary.
+// 2. Set the format to 24 hrs and binary.
+// 3. Verify the time to set. If it is an invalid time,
+// restore the time format and return EFI_INVALID_PARAMETER.
+// 4. Change the 4 digit year to a 2 digit year.
+// 5. Stop the RTC time.
+// 6. Store time and data on the RTC.
+// 7. Read the month, day, hour, minute, second.
+// 8. Start the RTC time.
+// 9. Restore the original time format.
+// 10. Return EFI_SUCCESS.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS EfiSetTime (
+ IN EFI_TIME *Time
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN TimeVarSize = sizeof(TIME_VARIABLE);
+ TIME_VARIABLE TimeVar;
+
+ //Check RTC Conditions and stuff
+ CheckRtc(TRUE);
+ if (Time == NULL) return EFI_INVALID_PARAMETER;
+ if (!VerifyTime(Time)) return EFI_INVALID_PARAMETER;
+ SetUpdate(FALSE);
+ WriteRtcIndex(ACPI_CENTURY_CMOS, Time->Year / 100);
+ WriteRtcIndex(RTC_YEAR_REG, Time->Year % 100);
+ WriteRtcIndex(RTC_MONTH_REG, Time->Month);
+ WriteRtcIndex(RTC_DAY_OF_MONTH_REG, Time->Day);
+ WriteRtcIndex(RTC_HOURS_REG, Time->Hour);
+ WriteRtcIndex(RTC_MINUTES_REG, Time->Minute);
+ WriteRtcIndex(RTC_SECONDS_REG, Time->Second);
+ SetUpdate(TRUE);
+
+ Status = pRS->GetVariable(
+ L"EfiTime",
+ &gEfiTimeVariableGuid,
+ NULL,
+ &TimeVarSize,
+ &TimeVar
+ );
+ if (EFI_ERROR(Status) || (TimeVar.TimeZone != Time->TimeZone) || (TimeVar.Daylight != Time->Daylight))
+ {
+ TimeVar.TimeZone = Time->TimeZone;
+ TimeVar.Daylight = Time->Daylight;
+ Status = pRS->SetVariable(
+ L"EfiTime",
+ &gEfiTimeVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof(TIME_VARIABLE),
+ &TimeVar
+ );
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: EfiGetWakeupTime
+//
+// Description:
+// Read the wake time. Read the status if it is enabled or if the system
+// has woken up.
+//
+// Input:
+// OUT BOOLEAN *Enabled - Flag indicating the validity of wakeup time
+// OUT BOOLEAN *Pending - Check if wake up time has expired.
+// OUT EFI_TIME *Time - Current wake up time setting
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS (Always)
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Read the original time format 12/24 hours and BCD/binary.
+// 2. Set the format to 24 hrs and binary.
+// 3. Read the status if the wake up time is enabled or if it has expired.
+// 4. Set the wakeup time.
+// 5. Restore the original time format.
+// 6. Return EFI_SUCCESS.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS EfiGetWakeupTime (
+ OUT BOOLEAN *Enabled,
+ OUT BOOLEAN *Pending,
+ OUT EFI_TIME *Time
+)
+{
+ RTC_REG_B RegB;
+ RTC_REG_C RegC;
+ RTC_REG_D RegD;
+ BOOLEAN IntState, SmiState;
+ EFI_STATUS Status;
+
+ if (!Enabled || !Pending || !Time) return EFI_INVALID_PARAMETER;
+
+ //Check RTC Conditions (24h Mode and BCD is ON)
+ Status = CheckRtc(FALSE);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Get SMI State and disable it
+ SmiState = SbLib_GetSmiState();
+ SbLib_SmiDisable();
+ //Get INTERRUPT State and disable it
+ IntState = CPULib_GetInterruptState();
+ CPULib_DisableInterrupt();
+
+ // Wait till RTC is safe to read,
+ CheckUpdateCmplete();
+ if(gTimeOut){
+ InitRtc();
+ }
+
+ Time->Hour = ReadRtcIndex(RTC_HOURS_ALARM_REG);
+ Time->Minute = ReadRtcIndex(RTC_MINUTES_ALARM_REG);
+ Time->Second = ReadRtcIndex(RTC_SECONDS_ALARM_REG);
+
+ //Restore SMIs and INTERRUPT State
+ if(IntState) CPULib_EnableInterrupt();
+ if(SmiState) SbLib_SmiEnable();
+
+
+ RegD.REG_D = ReadRtcIndex(RTC_REG_D_INDEX);
+ Time->Day = BCDToDec(RegD.DateAlarm);
+
+ RegB.REG_B=ReadRtcIndex(RTC_REG_B_INDEX);
+ RegC.REG_C=ReadRtcIndex(RTC_REG_C_INDEX);
+
+ *Enabled = RegB.AlarmInt;
+ *Pending = RegC.AlarmFlag;
+
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: EfiSetWakeupTime
+//
+// Description:
+// Enable/disable and set wakeup time
+//
+// Input:
+// IN BOOLEAN Enable - Flag indicating whether to enable/disble the time
+// IN EFI_TIME *Time - Time to set as the wake up time - OPTIONAL
+//
+// Output:
+// EFI_SUCCESS - Time is Set and/or Enabled/Disabled.
+// EFI_INVALID_PARAMETER - Invalid time or enabling with a NULL Time.
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Read the original time format 12/24 hours and BCD/binary.
+// 2. If Time is not NULL,
+// a. Verify the wakeup time to set. If it is an invalid time,
+// restore the time format and return EFI_INVALID_PARAMETER.
+// b. Set the wakeup time.
+// 3. If Time is NULL and Enable is true, restore original time format
+// and return EFI_INVALID_PARAMETER.
+// 4. Enable/Disable wakeup.
+// 5. Restore the original time format.
+// 6. Return EFI_SUCCESS.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS EfiSetWakeupTime (
+ IN BOOLEAN Enable,
+ IN EFI_TIME *Time OPTIONAL
+)
+{
+ RTC_REG_B RegB;
+ RTC_REG_D RegD;
+ UINT8 Day = 0;
+ EFI_STATUS Status;
+
+
+ //Check RTC Conditions (24h Mode and BCD is ON)
+ Status=CheckRtc(FALSE);
+ if(EFI_ERROR(Status)) return Status;
+
+ if (Enable){
+ //According to UEFI specification,
+ // value of 0 is invalid for the alarm day.
+ // However, RTC chip supports value 0.
+ // It interprets it as "every day".
+ //If this functionality is required,
+ //uncomment the following workaround.
+ //The workaround is commented out be default
+ //for compatibility with UEFI specification
+ //(one of the SCT tests fails with the workaround enabled).
+/*
+ if(Time != NULL) {
+ Day = Time->Day;
+ if(Time->Day == 0) Time->Day = 1;
+ }
+*/
+ if (Time == NULL || !VerifyTime(Time)) return EFI_INVALID_PARAMETER;
+ }
+
+ RegB.REG_B = ReadRtcIndex(RTC_REG_B_INDEX);
+ RegD.REG_D = ReadRtcIndex(RTC_REG_D_INDEX);
+ Day = DecToBCD(Day);
+ RegD.DateAlarm = Day;
+
+ SetUpdate(FALSE);
+ if(Time!=NULL){
+ WriteRtcIndex(RTC_HOURS_ALARM_REG, Time->Hour);
+ WriteRtcIndex(RTC_MINUTES_ALARM_REG, Time->Minute);
+ WriteRtcIndex(RTC_SECONDS_ALARM_REG, Time->Second);
+ WriteRtcIndex(RTC_REG_D_INDEX, RegD.REG_D); //Day==0 means don't care
+ }
+ //Set Enable/Disable
+ RegB.AlarmInt = Enable;
+ WriteRtcIndex(RTC_REG_B_INDEX, RegB.REG_B);
+
+ SetUpdate(TRUE);
+
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: NotInSmmTimeServ
+//
+// Description:
+// This function checks the date and time stored in the RTC. If it's wrong
+// it resets the time and and installs Time Runtime services in Non-SMM Mode
+// RTC Arch Protocol would also be installed.
+//
+// Input:
+// IN EFI_HANDLE ImageHandle - Image handle
+// IN EFI_SYSTEM_TABLE *SystemTable - pointer to the UEFI System Table
+//
+// Output:
+// Returns the EFI_STATUS value returned by the
+// InstallMultipleProtocolInterface function
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS NotInSmmTimeServ(
+ EFI_HANDLE ImageHandle,
+ EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_TIME Time;
+ EFI_HANDLE Handle = NULL;
+
+ InitAmiRuntimeLib(ImageHandle, SystemTable, NULL, NULL);
+
+ //Make Sure Mode, Format and REG_A is OK
+ CheckRtc(TRUE);
+
+ Status=EfiGetTime(&Time, NULL);
+
+ if( EFI_ERROR(Status) || (!VerifyTime(&Time)))
+ {
+ EFI_TIME nt;
+
+ ERROR_CODE(GENERIC_BAD_DATE_TIME_ERROR, EFI_ERROR_MINOR);
+
+ TRACE((TRACE_ALWAYS, "\n\nTime: %d/%d/%d %d:%d:%d\n",
+ Time.Month,
+ Time.Day,
+ Time.Year,
+ Time.Hour,
+ Time.Minute,
+ Time.Second
+ ));
+
+ TRACE((TRACE_ALWAYS, "Nanosecond: %d TimeZone: %d\n\n\n",
+ Time.Nanosecond,
+ Time.TimeZone
+ ));
+
+ //if Time is invalid the battery probably has been removed
+ //Let's setup RTC_REG_A just in case...
+ WriteRtcIndex(RTC_REG_A_INDEX, 0x26);
+
+ //Check to see what part of EFI_TIME was wrong.
+ //reset unrelated to RTC fields.
+ Time.TimeZone = EFI_UNSPECIFIED_TIMEZONE;
+ Time.Daylight = 0;
+ Time.Nanosecond = 0;
+
+ nt=Time;
+
+ nt.Hour = 0;
+ nt.Minute = 0;
+ nt.Second = 0;
+
+ if(VerifyTime(&nt)){
+ //if we here that means Time was wrong
+ Time.Hour = 0;
+ Time.Minute = 0;
+ Time.Second = 0;
+ } else {
+ //if we here that means Date was wrong
+ Time.Month = DEFAULT_MONTH;
+ Time.Day = DEFAULT_DAY;
+ Time.Year = DEFAULT_YEAR;
+ }
+ //Here is the situation when both Time and Date is Incorrect.
+ if(!VerifyTime(&Time)){
+ Time.Hour = 0;
+ Time.Minute = 0;
+ Time.Second = 0;
+ Time.Month = DEFAULT_MONTH;
+ Time.Day = DEFAULT_DAY;
+ Time.Year = DEFAULT_YEAR;
+ }
+
+ TRACE((TRACE_ALWAYS, "Reseting Invalid Date and Time to: %d/%d/%d %d:%d:%d\n\n",
+ Time.Month,
+ Time.Day,
+ Time.Year,
+ Time.Hour,
+ Time.Minute,
+ Time.Second
+ ));
+ EfiSetTime(&Time);
+ }
+ // Install runtime services
+
+ pRS->GetTime = EfiGetTime;
+ pRS->SetTime = EfiSetTime;
+ pRS->GetWakeupTime = EfiGetWakeupTime;
+ pRS->SetWakeupTime = EfiSetWakeupTime;
+
+ //This protocol is to notify core that the Runtime Table has been updated, so
+ //it can update the runtime table CRC.
+ Status = pBS->InstallMultipleProtocolInterfaces(
+ &Handle,
+ &gEfiRealTimeClockArchProtocolGuid,NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: NotInSmmResetServ
+//
+// Description:
+// Installs Reset Runtime Services in Non-SMM Mode
+// Reset Architectural Protocol is installed
+//
+// Input:
+// IN EFI_HANDLE ImageHandle - Image handle
+// IN EFI_SYSTEM_TABLE *SystemTable - pointer to the UEFI System Table
+//
+// Output:
+// Returns the EFI_STATUS value returned by the InstallProtocolInterface
+// function
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+EFI_STATUS NotInSmmResetServ(
+ EFI_HANDLE ImageHandle,
+ EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_HANDLE ResetProtocolHandle = NULL;
+
+ InitAmiRuntimeLib(ImageHandle, SystemTable, NULL, NULL);
+
+ // Install reset services
+ pRS->ResetSystem = EfiResetSystem;
+
+ Status = pBS->InstallProtocolInterface ( &ResetProtocolHandle,
+ &gEfiResetArchProtocolGuid, EFI_NATIVE_INTERFACE,
+ NULL);
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: InSmmTimeServ
+//
+// Description:
+// Installs Time Runtime Services to SMM mode.
+//
+//
+// Input:
+// IN EFI_HANDLE ImageHandle - Image handle
+// IN EFI_SYSTEM_TABLE *SystemTable - pointer to the UEFI System Table
+//
+// Output:
+// EFI_SUCCESS
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+EFI_STATUS InSmmTimeServ(
+ EFI_HANDLE ImageHandle,
+ EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (pST->RuntimeServices != pRS)
+ {
+
+ pRS->GetTime = EfiGetTime;
+ pRS->SetTime = EfiSetTime;
+ pRS->GetWakeupTime = EfiGetWakeupTime;
+ pRS->SetWakeupTime = EfiSetWakeupTime;
+
+ }
+ return EFI_SUCCESS;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: InSmmResetServ
+//
+// Description:
+// Installs Reset runtime services to SMM mode.
+//
+// Input:
+// IN EFI_HANDLE ImageHandle - Image handle
+// IN EFI_SYSTEM_TABLE *SystemTable - pointer to the UEFI System Table
+//
+// Output:
+// EFI_SUCCESS
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+EFI_STATUS InSmmResetServ(
+ EFI_HANDLE ImageHandle,
+ EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (pST->RuntimeServices != pRS)
+ {
+ pRS->ResetSystem = EfiResetSystem;
+ }
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: TimeServInit
+//
+// Description:
+// This function is the entry point for this DXE. This function installs
+// Time pRS services
+//
+// Input:
+// IN EFI_HANDLE ImageHandle - Image handle
+// IN EFI_SYSTEM_TABLE *SystemTable - pointer to the UEFI System Table
+//
+// Output:
+// Return Status based on errors that occurred while waiting for time to expire.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+TimeServInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+){
+ InitAmiLib(ImageHandle, SystemTable);
+ return InitSmmHandlerEx(ImageHandle, SystemTable, InSmmTimeServ, NotInSmmTimeServ);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ResetServInit
+//
+// Description:
+// This function is the entry point for this DXE Driver. This function
+// installs the Reset pRS service.
+//
+// Input:
+// IN EFI_HANDLE ImageHandle - Image handle
+// IN EFI_SYSTEM_TABLE *SystemTable - pointer to the UEFI System Table
+//
+// Output:
+// Return Status based on errors that occurred while waiting for time to expire.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ResetServInit(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+){
+ InitAmiLib(ImageHandle, SystemTable);
+ return InitSmmHandlerEx(ImageHandle, SystemTable, InSmmResetServ, NotInSmmResetServ);
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************