diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /Core/EM/Runtime | |
download | zprj-master.tar.xz |
Diffstat (limited to 'Core/EM/Runtime')
-rw-r--r-- | Core/EM/Runtime/CpuIoDxe.c | 547 | ||||
-rw-r--r-- | Core/EM/Runtime/Flash.c | 1014 | ||||
-rw-r--r-- | Core/EM/Runtime/Runtime.c | 579 | ||||
-rw-r--r-- | Core/EM/Runtime/Runtime.cif | 10 | ||||
-rw-r--r-- | Core/EM/Runtime/Runtime.dxs | 49 | ||||
-rw-r--r-- | Core/EM/Runtime/Runtime.mak | 102 | ||||
-rw-r--r-- | Core/EM/Runtime/Runtime.sdl | 129 | ||||
-rw-r--r-- | Core/EM/Runtime/RuntimeSrc.cif | 13 | ||||
-rw-r--r-- | Core/EM/Runtime/RuntimeSrc.mak | 74 | ||||
-rw-r--r-- | Core/EM/Runtime/RuntimeSrc.sdl | 57 | ||||
-rw-r--r-- | Core/EM/Runtime/TimeAndReset.C | 1191 |
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 ** +//** ** +//********************************************************************** +//********************************************************************** |