From b7c51c9cf4864df6aabb99a1ae843becd577237c Mon Sep 17 00:00:00 2001 From: raywu Date: Fri, 15 Jun 2018 00:00:50 +0800 Subject: init. 1AQQW051 --- Core/EM/S3/BootScriptSave.c | 2540 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2540 insertions(+) create mode 100644 Core/EM/S3/BootScriptSave.c (limited to 'Core/EM/S3/BootScriptSave.c') diff --git a/Core/EM/S3/BootScriptSave.c b/Core/EM/S3/BootScriptSave.c new file mode 100644 index 0000000..46e2bc4 --- /dev/null +++ b/Core/EM/S3/BootScriptSave.c @@ -0,0 +1,2540 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/S3/BootScriptSave.c 5 7/15/14 9:51p Chienhsieh $ +// +// $Revision: 5 $ +// +// $Date: 7/15/14 9:51p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/S3/BootScriptSave.c $ +// +// 5 7/15/14 9:51p Chienhsieh +// update for ACPI module labeled 49 +// +// 12 4/14/14 3:10p Oleksiyy +// [TAG] EIP161916 +// [Category] Improvement +// [Description] 32 bit typecasting issue fixed. +// [Files] BootScriptSave.c +// +// 4 9/17/13 10:03p Thomaschen +// update for ACPI module labeled 47 +// +// 11 8/14/13 12:35p Oleksiyy +// [TAG] EIP95347 +// [Category] Improvement +// [Description] Synchronized usage of Allocate/Free memory operations +// on pool/page basis. +// +// [Files] BootScriptSave.c +// +// 10 7/05/13 2:32p Oleksiyy +// [TAG] EIP128054 +// [Category] Improvement +// [Description] USB ports are disabled after resume from S3 with +// special steps +// [Files] BootScriptSave.c +// +// 9 12/27/12 4:00p Oleksiyy +// [TAG] EIP109790 +// [Category] Improvement +// [Description] Code check result - Possible Null pointer acces. +// [Files] BootScriptSave.c +// +// 8 12/13/12 12:03p Oleksiyy +// [TAG] EIP109290 +// [Category] Improvement +// [Description] Issues found by CppCheck in ACPI eModule +// [Files] AcpiCore.c, mptable.c, AmlString.c, BootScriptSave.c and +// BootScriptExecuter.c +// +// 7 10/31/12 3:49p Oleksiyy +// [TAG] EIP104782 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Bug in BootScriptSave.c AllocTableEntry() function +// [RootCause] Pointer to ACPI_VARIABLE_SET was not initialized. +// [Solution] Initialize pointer. +// [Files] BootScriptSave.c +// +// 6 12/16/11 4:27p Oleksiyy +// [TAG] EIP78247 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] BootScriptTable problem +// [RootCause] TablePointer was updated uncorectly during CloseTable +// call and any opcodes added after closing was ignored. +// [Solution] Pointer updated correctly now. +// [Files] BootScriptSave.c +// +// 5 9/29/11 5:05p Oleksiyy +// [TAG] EIP71372 +// [Category] Improvement +// [Description] EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE added. +// [Files] BootScriptExecuter.c and BootScriptSave.c +// +// 4 6/16/11 9:57a Felixp +// Bug fix: EFI_BOOT_SCRIPT_PCI_POLL_OPCODE is replaced with +// EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE +// +// 3 5/13/11 4:59p Oleksiyy +// [TAG] EIP56650 +// [Category] Improvement +// [Description] Compatibility with older core fixed. +// [Files] BootScriptSave.c +// +// 2 5/13/11 3:20p Oleksiyy +// [TAG] EIP56650 +// [Category] New Feature +// [Description] S3 Save State Protocol and S3 Smm Save State Protocol +// functions added. Support for opcodes introduced in PI 1.2 added. +// +// [Files] BootScriptCommon.h, BootScriptExecuter.c, +// BootScriptPrivate.h, BootScriptSave.c and BootScriptSave.h +// +// 1 2/03/11 4:08p Oleksiyy +// [TAG] EIP53402 +// [Category] Improvement +// [Description] Create new label of ACPI with separate S3 Functionality +// [Files] S3Save.cif +// S3Save.sdl +// S3Save.mak +// AcpiS3.h +// AcpiS3Save.c +// BootScriptPrivate.h +// BootScriptSave.c +// AcpiS3Save.dxs +// SmmS3Save.dxs +// +// 8 1/20/11 12:33p Oleksiyy +// [TAG] EIP48697 +// [Category] Improvement +// [Description] Functionality modified and after Close table is called +// - boot script still added to the end of the table. +// [Files] BootScriptSave.c +// +// 7 11/05/09 4:02p Oleksiyy +// EIP 27821 Support for 64 bit operations in Bootscript added. To use +// this functions AmiLib.h, CpuIo.c, IA32CLib.c, PciCfg.c, x64AsmLib.asm +// files should be updated also. +// +// 6 3/26/09 4:51p Oleksiyy +// New ACPI Core implementation - improves logic, execution time and +// memory usage of ACPI module. +// +// 5 3/26/09 10:10a Oleksiyy +// EIP 20471 : MAX_TABLE_ENTRIES value increased to 2048. +// +// 4 12/01/08 6:52p Yakovlevs +// Fixed BootScript code to support IA32 and x64 CPU Architecture EIP # +// 17317 +// +// 3 4/15/08 9:21p Yakovlevs +// Functions Headers added +// +// 2 6/05/07 12:19a Felixp +// Added SmmBus support +// +// 1 4/23/07 1:31p Felixp +// +// 14 3/21/07 10:53a Markw +// Previous revision over wrote Felix's changes. I put them back. +// +// 13 3/19/07 4:13p Markw +// Update so that PCI functions saving registers 0xfc - 0xff doesn't fail. +// +// 12 2/12/07 11:21a Felixp +// Revision field removed from EFI_BOOT_SCRIPT_SAVE_PROTOCOL structure +// to match BootScript spec (it was earlier their for Tiano compliance. +// Tiano header is fixed now). +// +// 11 12/26/06 2:57p Markw +// Add BootScript Polling. +// +// 10 9/29/06 6:02p Markw +// Fix 64-bit bugs. +// +// 9 9/22/06 6:09p Markw +// 64-bit fix. +// +// 8 8/24/06 10:11a Felixp +// x64 support: warning/error fixes +// +// 7 3/13/06 5:30p Felixp +// +// 6 11/07/05 3:44p Sivagarn +// Included SMBus.H to resolve SMBus related definition errors +// +// 5 6/23/05 5:38p Markw +// Added include to boot script save protocol. Previously was in +// bootscriptprivate.h. +// +// 4 5/13/05 3:19p Markw +// UINT32 -> UINT64 sometimes causes sign extend. Clear bits[64:32] for +// address. +// +// 3 3/23/05 2:53p Markw +// Bug fixes: Pointers, TableLength +// +// 2 3/14/05 4:25p Markw +// Change final memory allocation to Runtime Service Data to ACPI NVS. +// +//********************************************************************** + + +// +//--------------------------------------------------------------------------- +// +// Name: BootScriptSave.c +// +// Description: Save Mem/Io/Pci/Smbus/etc into a table. The script will +// be executed on a S3 resume. +// +//--------------------------------------------------------------------------- +// +#if PI_SPECIFICATION_VERSION>=0x0001000A +#include +#include +#include +#endif +#include +#include +#include "BootScriptPrivate.h" +#include +#include "AcpiS3.h" +//---For Compatibility Reasons--------------------------------------------------- +#ifndef EFI_BOOT_SCRIPT_IO_POLL_OPCODE_OEM +#define EFI_BOOT_SCRIPT_IO_POLL_OPCODE_OEM EFI_BOOT_SCRIPT_IO_POLL_OPCODE +#define EFI_BOOT_SCRIPT_MEM_POLL_OPCODE_OEM EFI_BOOT_SCRIPT_MEM_POLL_OPCODE +#define EFI_BOOT_SCRIPT_PCI_POLL_OPCODE_OEM EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE +#endif +// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +// Currently reentrant code could fail if reentered when new table +// is being created. +// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +#if PI_SPECIFICATION_VERSION>=0x0001000A +EFI_SMM_SYSTEM_TABLE2 *gSmst2 = NULL; +EFI_SMM_BASE2_PROTOCOL *mInternalSmmBase2 = NULL; +EFI_HANDLE mSmmS3SaveHandle = NULL; +#endif + +EFI_EVENT gEvtReadyToBoot; + +typedef EFI_STATUS (*GENERIC_OPCODE_FUNC) ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + va_list List +); + + +#define INIT_TABLE_SIZE 1024 +#define MAX_TABLE_ENTRIES 2048 +#define TBL_VAR_NAME L"S3SS" + + + +static EFI_GUID gEfiBootScriptSaveGuid = EFI_BOOT_SCRIPT_SAVE_GUID; +static EFI_GUID gTableDataVarGuid = { 0x4bafc2b4, 0x2dc, 0x4104, 0xb2, 0x36, 0xd6, 0xf1, 0xb9, 0x8d, 0x9e, 0x84}; + + +typedef struct { + VOID *TableBottom; + VOID *TablePtr; + UINTN TableSize; + UINTN NumTableEntries; + BOOLEAN WasClosed; +} TABLE_INFO; + +#if PI_SPECIFICATION_VERSION>=0x0001000A + +typedef struct { + BOOLEAN IsItInsert; + BOOLEAN BeforeOrAfter; + UINTN Position; +} BOOT_SCRIPT_INSERT_INFO; + +BOOT_SCRIPT_INSERT_INFO gInsertInfo = {FALSE, FALSE, 0}; +#define LABEL_MAX_SIZE 0x200 +#endif + +TABLE_INFO *gTableInfo = NULL; + +// +//--------------------------------------------------------------------------- +// Procedure: NewTable +// +// Description: Initialize first table. +// +// Input: +// IN UINT16 Table +// +// Output: +// BOOLEAN - TRUE if new table created. +// +// Notes: +// Return True if successful table creation, otherwise return false. +// Need valid table info even if table fails, because functions may +// attempt to write to the boot script without a table being created. +// +//--------------------------------------------------------------------------- +// +BOOLEAN NewTable() +{ + EFI_STATUS Status; +//-------------------------------- + + Status = pBS->AllocatePool(EfiBootServicesData, INIT_TABLE_SIZE*2, &(gTableInfo->TableBottom)); + if (EFI_ERROR(Status)) + { + gTableInfo->TableBottom = 0; + return FALSE; + } + gTableInfo->TablePtr = gTableInfo->TableBottom; + gTableInfo->TableSize = INIT_TABLE_SIZE*2; + gTableInfo->NumTableEntries = 0; + gTableInfo->WasClosed = FALSE; + return TRUE; + +} + + +// +//--------------------------------------------------------------------------- +// Procedure: InitBootScriptStructure +// +// Description: Updates Table pointer Before each Write operation. +// +// Input: +// IN UINT16 Table +// +// Output: +// EFI_SATUS - Status of the operation. +// +// Notes: +// Return True if successful table creation, otherwise return false. +// Need valid table info even if table fails, because functions may +// attempt to write to the boot script without a table being created. +// +//--------------------------------------------------------------------------- +// + +EFI_STATUS InitBootScriptStructure(BOOLEAN IsItSmm) +{ +#if PI_SPECIFICATION_VERSION>=0x0001000A + UINTN sz=sizeof(VOID*); +#endif + EFI_STATUS Status = EFI_SUCCESS; + +//-------------------------------- + if(gTableInfo == NULL) + { +#if PI_SPECIFICATION_VERSION>=0x0001000A + Status = pRS->GetVariable(L"S3SS", &gTableDataVarGuid, NULL, &sz, &gTableInfo); + if(EFI_ERROR(Status) && Status!=EFI_NOT_FOUND && IsItSmm) return EFI_OUT_OF_RESOURCES; + if(Status==EFI_NOT_FOUND) +#endif + { + EFI_PHYSICAL_ADDRESS MaxAddress = 0xFFFFFFFF; + Status = pBS->AllocatePages(AllocateMaxAddress, EfiReservedMemoryType, EFI_SIZE_TO_PAGES(sizeof(TABLE_INFO)), + &MaxAddress); + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) return EFI_OUT_OF_RESOURCES; + gTableInfo = (VOID*)(UINTN)MaxAddress; + if (!NewTable()) return EFI_OUT_OF_RESOURCES; +#if PI_SPECIFICATION_VERSION>=0x0001000A + Status = pRS->SetVariable(L"S3SS",&gTableDataVarGuid, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS), + sz, &gTableInfo); + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status) && IsItSmm) return EFI_OUT_OF_RESOURCES; +#endif + } + + + } + return Status; +} +#if PI_SPECIFICATION_VERSION>=0x0001000A +// +//--------------------------------------------------------------------------- +// Procedure: InsertPositionInBootScript +// +// Description: Found position and, based on Size, allocate space for Entry, +// that has to be incerted, in table based on parameters in +// gInsertInfo structure. +// +// Input: +// IN UINTN Size - Size of entry to allocate in table. +// +// Output: +// VOID * - Pointer to allocated entry in table. +// +// +//--------------------------------------------------------------------------- +// +VOID* InsertPositionInBootScript (UINTN Size) +{ + TABLE_INFO *Info = gTableInfo; + UINT8 *CopyFrom = Info->TableBottom, *CopyTo; + UINTN i = 0, CopySize = (UINT8*)Info->TablePtr - (UINT8*)Info->TableBottom; + BOOLEAN Found = FALSE; + + if (gInsertInfo.Position != -1) + { + for (i=0; iNumTableEntries; i++) + { //Found position with supplied + if (((BOOT_SCRIPT_INFO_STRUCTURE*) CopyFrom)->UniqueIndex == gInsertInfo.Position) + { + Found = TRUE; + if (gInsertInfo.BeforeOrAfter == FALSE) + CopyFrom += ((BOOT_SCRIPT_INFO_STRUCTURE*) CopyFrom)->Length; + break; + } + CopyFrom += ((BOOT_SCRIPT_INFO_STRUCTURE*) CopyFrom)->Length; + } + if (!Found) return NULL; + } + if ((Size != 0) && (i != Info->NumTableEntries)) + { + CopyTo = CopyFrom + Size; + CopySize = (UINT8*)Info->TablePtr - CopyFrom; + MemCpy(CopyTo, CopyFrom, CopySize); + } + return CopyFrom; + +} +#endif +// +//--------------------------------------------------------------------------- +// Procedure: AllocTableEntry +// +// Description: Allocate Entry from table. If not enough space, create +// larger table and return entry. +// +// Input: +// IN UINTN Size - Size of entry to allocate in table. +// +// Output: +// VOID * - Pointer to allocated entry in table. +// +// Notes: +// Here is the control flow of this function: +// 1. Does the BootScript table exist. If no return 0. +// 2. Does table contain max entries? If so assert. +// 3. Enough space in the table for the boot script call? If yes, go to step 8. +// ---Create table--- +// 4. Get Size of table needed for entry. (A multiple of INIT_TABLE_SIZE.) +// 5. Allocate new table. +// 6. Copy old table +// 7. Free old table. +// 8. Update gTableInfo data. +// ------------------ +// 9. Adjust allocation pointer to allocate new space. +// 10. Return newly allocated space. +// +//--------------------------------------------------------------------------- +// + +VOID * AllocTableEntry(IN UINTN Size) +{ + TABLE_INFO *Info = gTableInfo; + VOID *TempBottom; + VOID *TempPtr; + UINTN TempSize, NewSize; + BOOT_SCRIPT_TABLE_END TableEnd; +#if PI_SPECIFICATION_VERSION>=0x0001000A + //BOOT_SCRIPT_INFO_STRUCTURE BsHeader; + Size += sizeof(BOOT_SCRIPT_INFO_STRUCTURE); +#endif + if (Info->TableBottom == NULL) return NULL; + + //Should not fill table. If table becomes full, then an error is causing too many table entries. + ASSERT(Info->NumTableEntries < MAX_TABLE_ENTRIES); + + if ((UINTN)Info->TableBottom + Info->TableSize < (UINTN) Info->TablePtr + Size + + sizeof(BOOT_SCRIPT_TABLE_END) +#if PI_SPECIFICATION_VERSION>=0x0001000A + + sizeof(BOOT_SCRIPT_INFO_STRUCTURE) +#endif + ) + { +#if PI_SPECIFICATION_VERSION>=0x0001000A + if (gSmst2 != NULL) return NULL; // we can't allocate memory in SMM +#endif + TempSize = Info->TableSize + INIT_TABLE_SIZE * (Size / INIT_TABLE_SIZE + 1); + + if (Info->WasClosed == FALSE) // Use AllocatePool if table was not closed - later it will be copyed under 4 Gb. + { + if (pBS->AllocatePool(EfiBootServicesData, TempSize, &TempBottom) != EFI_SUCCESS) + return NULL; + + NewSize = TempSize; + } + else // Use AllocatePages if table was closed. We need it under 4 Gb. + { + EFI_PHYSICAL_ADDRESS MaxAddress = 0xFFFFFFFF; + + if (pBS->AllocatePages(AllocateMaxAddress, EfiReservedMemoryType, + EFI_SIZE_TO_PAGES(TempSize) + 1, &MaxAddress) != EFI_SUCCESS) + return NULL; + TempBottom = (VOID*)(UINTN)MaxAddress; + NewSize = EFI_PAGES_TO_SIZE(EFI_SIZE_TO_PAGES(TempSize) + 1); // Calculate the sieze of new structure from pages + TempSize = EFI_SIZE_TO_PAGES(Info->TableSize); // Save old size in pages to use in FreePages. + } + + MemCpy(TempBottom, Info->TableBottom, Info->TableSize); + + Info->TablePtr = (UINT8*)TempBottom + (UINTN)Info->TablePtr - (UINTN)Info->TableBottom; + TempPtr = Info->TableBottom; // Save old TableBottom to freememory + Info->TableBottom = TempBottom; + Info->TableSize = NewSize; + if (Info->WasClosed == TRUE) + { + EFI_STATUS Status; + ACPI_VARIABLE_SET *AcpiVariableSet = NULL; + CHAR16 AcpiGlobalVariable[] = ACPI_GLOBAL_VARIABLE; + EFI_GUID EfiAcpiVariableGuid = EFI_ACPI_VARIABLE_GUID; + UINTN VariableSize = sizeof(ACPI_VARIABLE_SET*); + Status = pRS->GetVariable( + AcpiGlobalVariable, + &EfiAcpiVariableGuid, + NULL, + &VariableSize, + &AcpiVariableSet + ); + ASSERT_EFI_ERROR(Status); + AcpiVariableSet->AcpiBootScriptTable = (EFI_PHYSICAL_ADDRESS) (UINTN) TempBottom; + pBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) TempPtr, TempSize); // If WasClosed == TRUE use FreePages + } + else pBS->FreePool(TempPtr); // If WasClosed != TRUE use FreePool + + } +#if PI_SPECIFICATION_VERSION>=0x0001000A + if (gInsertInfo.IsItInsert == TRUE) + { + TempPtr = InsertPositionInBootScript (Size); + if (TempPtr == NULL) return TempPtr; + } + else +#endif + TempPtr = (UINT8*)Info->TablePtr; + Info->TablePtr = (UINT8*)Info->TablePtr + Size; +#if PI_SPECIFICATION_VERSION>=0x0001000A + ((BOOT_SCRIPT_INFO_STRUCTURE*)TempPtr)->UniqueIndex = (UINT32) Info->NumTableEntries; + ((BOOT_SCRIPT_INFO_STRUCTURE*)TempPtr)->Length = (UINT32) Size; + TempPtr = (UINT8*) TempPtr + sizeof(BOOT_SCRIPT_INFO_STRUCTURE); +#endif + TableEnd.Type = TABLE_END_OP_CODE; + MemCpy((VOID*)((UINTN)Info->TablePtr +#if PI_SPECIFICATION_VERSION>=0x0001000A + + sizeof(BOOT_SCRIPT_INFO_STRUCTURE) +#endif + ), &TableEnd, sizeof(BOOT_SCRIPT_TABLE_END)); + ++(Info->NumTableEntries); + return TempPtr; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: BootScriptIoWrite +// +// Description: Write to boot script table an IoWrite. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN va_list arglist +// +// Output: +// EFI_STATUS +// +// Notes: +// Here is the control flow of this function: +// 1. Get variable argument list from stack. +// 2. Validate argument list. If invalid return EFI_INVALID_PARAMETER; +// 3. Allocate entry from table. If no room in table, return EFI_OUT_OF_RESOURCES. +// 4. Fill fixed table entries. +// 5. Add data to end of fixed table. +// 6. Return EFI_SUCCESS. +// +//--------------------------------------------------------------------------- +// +EFI_STATUS BootScriptIoWrite ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + IN va_list arglist + ) +{ + EFI_BOOT_SCRIPT_WIDTH Width = va_arg(arglist, EFI_BOOT_SCRIPT_WIDTH); + + UINT64 Address = va_arg(arglist, UINT64); + UINTN Count = va_arg(arglist, UINTN); + VOID *Buffer = va_arg(arglist, VOID*); + + BOOT_SCRIPT_WRITE_IO WriteIo; + VOID *Ptr; + UINT8 ValueSize = (UINT8) (1 << (Width & 3)); + UINTN AddressCount; + + AddressCount = ValueSize * ( ((Width & ~3) != EfiBootScriptWidthFifoUint8 ) ? Count : 1); + + //---Validate Inputs--- + if (!Count) return EFI_INVALID_PARAMETER; + if (Address + AddressCount > 0xffff) return EFI_INVALID_PARAMETER; + + + //---Fill and Copy Table--- + Ptr = AllocTableEntry((UINT32)sizeof(BOOT_SCRIPT_WRITE_IO) + AddressCount); + if (Ptr == 0) return EFI_OUT_OF_RESOURCES; + + WriteIo.Type = (UINT16) TABLE_TYPE2(EFI_BOOT_SCRIPT_IO_WRITE_OPCODE,Width); + WriteIo.Port = (UINT16) Address; + WriteIo.Count = Count; + + MemCpy(Ptr, &WriteIo, sizeof(BOOT_SCRIPT_WRITE_IO)); //Use MemCpy to avoid alignment problems. + Ptr = (UINT8*) Ptr + sizeof(BOOT_SCRIPT_WRITE_IO); + + MemCpy(Ptr, Buffer, AddressCount); + + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: BootScriptIoReadWrite +// +// Description: Write to boot script table a IoReadWrite. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN va_list arglist +// +// Output: +// EFI_STATUS +// +// Notes: +// Here is the control flow of this function: +// 1. Get variable argument list from stack. +// 2. Validate argument list. If invalid return EFI_INVALID_PARAMETER; +// 3. Allocate entry from table. If no room in table, return EFI_OUT_OF_RESOURCES. +// 4. Fill fixed table entries. +// 5. Return EFI_SUCCESS. +// +//--------------------------------------------------------------------------- +// +EFI_STATUS BootScriptIoReadWrite ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + va_list arglist + ) +{ + EFI_BOOT_SCRIPT_WIDTH Width = va_arg(arglist, EFI_BOOT_SCRIPT_WIDTH); + UINT64 Address = va_arg(arglist, UINT64); + VOID *DataValue = va_arg(arglist, VOID *); + VOID *DataMask = va_arg(arglist, VOID *); + + BOOT_SCRIPT_READ_WRITE_IO ReadWriteIo; + VOID *Ptr; + UINT8 ValueSize = (UINT8) (1 << (Width & 3)); + UINT64 BitMask; + UINT64 Data, Mask; + + Mask = *(UINT64*)DataMask; + Data = *(UINT64*)DataValue; + + switch(Width&3) + { + case EfiBootScriptWidthUint8: BitMask = 0x00000000000000ff; break; + case EfiBootScriptWidthUint16: BitMask = 0x000000000000ffff; break; + case EfiBootScriptWidthUint32: BitMask = 0x00000000ffffffff; break; + default: BitMask = 0xffffffffffffffff; + } + + //---Validate Inputs--- + if (Address + ValueSize > 0xffff) return EFI_INVALID_PARAMETER; + + + //---Fill and Copy Table--- + Ptr = AllocTableEntry(sizeof(BOOT_SCRIPT_READ_WRITE_IO)); + if (Ptr == 0) return EFI_OUT_OF_RESOURCES; + + ReadWriteIo.Type = (UINT16) TABLE_TYPE2(EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE, Width); + ReadWriteIo.Port = (UINT16) Address; + ReadWriteIo.Value = Data & BitMask; + ReadWriteIo.Mask = Mask & BitMask; + + MemCpy(Ptr, &ReadWriteIo, sizeof(ReadWriteIo)); //Use MemCpy to avoid alignment problems. + + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: BootScriptMemWrite +// +// Description: Write to boot script table an MemWrite. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN va_list arglist +// +// Output: +// EFI_STATUS +// +// Notes: +// Here is the control flow of this function: +// 1. Get variable argument list from stack. +// 2. Validate argument list. If invalid return EFI_INVALID_PARAMETER; +// 3. Allocate entry from table. If no room in table, return EFI_OUT_OF_RESOURCES. +// 4. Fill fixed table entries. +// 5. Add data to end of fixed table. +// 6. Return EFI_SUCCESS. +// +//--------------------------------------------------------------------------- +// +EFI_STATUS BootScriptMemWrite ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + va_list arglist + ) +{ + EFI_BOOT_SCRIPT_WIDTH Width = va_arg(arglist, EFI_BOOT_SCRIPT_WIDTH); + + UINT64 Address = va_arg(arglist, UINT64); + UINTN Count = va_arg(arglist, UINTN); + VOID *Buffer = va_arg(arglist, VOID*); + + BOOT_SCRIPT_WRITE_MEM WriteMem; + VOID *Ptr; + UINT8 ValueSize = (UINT8) (1 << (Width & 3)); + UINTN AddressCount; + + AddressCount = ValueSize * ( ((Width & ~3) != EfiBootScriptWidthFifoUint8 ) ? Count : 1); + + //---Validate Inputs--- + if (!Count) return EFI_INVALID_PARAMETER; + +#if defined(EFI64) || defined(EFIx64) + if (Address + AddressCount < Address) return EFI_INVALID_PARAMETER; //Overflow +#else + Address &= 0xffffffff; //When UINT32 -> UINT64, compiler sometimes sign extends. + if (Address + AddressCount > 0xffffffff) return EFI_INVALID_PARAMETER; + +#endif + + //---Fill and Copy Table--- + Ptr = AllocTableEntry((UINT32)sizeof(BOOT_SCRIPT_WRITE_MEM) + AddressCount); + if (Ptr == 0) return EFI_OUT_OF_RESOURCES; + + WriteMem.Type = (UINT16)TABLE_TYPE2(EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE,Width); + WriteMem.Address = (UINT64)Address; + WriteMem.Count = Count; + + MemCpy(Ptr, &WriteMem, sizeof(BOOT_SCRIPT_WRITE_MEM)); //Use MemCpy to avoid alignment problems. + Ptr = (UINT8*) Ptr + sizeof(BOOT_SCRIPT_WRITE_MEM); + + MemCpy(Ptr, Buffer, AddressCount); + + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: BootScriptMemReadWrite +// +// Description: Write to boot script table an MemReadWrite. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN va_list arglist +// +// Output: +// EFI_STATUS +// +// Notes: +// Here is the control flow of this function: +// 1. Get variable argument list from stack. +// 2. Validate argument list. If invalid return EFI_INVALID_PARAMETER; +// 3. Allocate entry from table. If no room in table, return EFI_OUT_OF_RESOURCES. +// 4. Fill fixed table entries. +// 5. Return EFI_SUCCESS. +// +//--------------------------------------------------------------------------- +// +EFI_STATUS BootScriptMemReadWrite ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + va_list arglist + ) +{ + EFI_BOOT_SCRIPT_WIDTH Width = va_arg(arglist, EFI_BOOT_SCRIPT_WIDTH); + UINT64 Address = va_arg(arglist, UINT64); + VOID *DataValue = va_arg(arglist, VOID *); + VOID *DataMask = va_arg(arglist, VOID *); + + BOOT_SCRIPT_READ_WRITE_MEM ReadWriteMem; + VOID *Ptr; + UINT8 ValueSize = (UINT8) (1 << (Width & 3)); + UINT64 BitMask; + UINT64 Mask, Data; + + Mask = *(UINT64*)DataMask; + Data = *(UINT64*)DataValue; + + switch(Width&3) + { + case EfiBootScriptWidthUint8: BitMask = 0x00000000000000ff; break; + case EfiBootScriptWidthUint16: BitMask = 0x000000000000ffff; break; + case EfiBootScriptWidthUint32: BitMask = 0x00000000ffffffff; break; + default: BitMask = 0xffffffffffffffff; + } + + //---Validate Inputs--- +#if defined(EFI64) || defined(EFIx64) + if (Address + ValueSize < Address) return EFI_INVALID_PARAMETER; //Overflow +#else + Address &= 0xffffffff; //When UINT32 -> UINT64, compiler sometimes sign extends. + if (Address + ValueSize > 0xffffffff) return EFI_INVALID_PARAMETER; + +#endif + + //---Fill and Copy Table--- + Ptr = AllocTableEntry(sizeof(BOOT_SCRIPT_READ_WRITE_MEM)); + if (Ptr == 0) return EFI_OUT_OF_RESOURCES; + + ReadWriteMem.Type = (UINT16)TABLE_TYPE2(EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE, Width); + ReadWriteMem.Address = (UINT64)Address; + ReadWriteMem.Value = Data & BitMask; + ReadWriteMem.Mask = Mask & BitMask; + + MemCpy(Ptr, &ReadWriteMem, sizeof(BOOT_SCRIPT_READ_WRITE_MEM)); //Use MemCpy to avoid alignment problems. + + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: BootScriptPciWrite +// +// Description: Write to boot script table an PciWrite. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN va_list arglist +// +// Output: +// EFI_STATUS +// +// Notes: +// Here is the control flow of this function: +// 1. Get variable argument list from stack. +// 2. Validate argument list. If invalid return EFI_INVALID_PARAMETER; +// 3. Allocate entry from table. If no room in table, return EFI_OUT_OF_RESOURCES. +// 4. Fill fixed table entries. +// 5. Add data to end of fixed table. +// 6. Return EFI_SUCCESS. +// +//--------------------------------------------------------------------------- +// +EFI_STATUS BootScriptPciWrite ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + va_list arglist + ) +{ + EFI_BOOT_SCRIPT_WIDTH Width = va_arg(arglist, EFI_BOOT_SCRIPT_WIDTH); + + UINT64 Address = va_arg(arglist, UINT64); + UINTN Count = va_arg(arglist, UINTN); + VOID *Buffer = va_arg(arglist, VOID*); + + BOOT_SCRIPT_WRITE_PCI WritePci; + VOID *Ptr; + UINT8 ValueSize = (UINT8) (1 << (Width & 3)); + UINTN AddressCount; + UINT16 Register; + UINT16 RegisterMax; + if (((Width & 3) == EfiBootScriptWidthUint16) && (Address & 0x01)) + return EFI_INVALID_PARAMETER; + if (((Width & 3) >= EfiBootScriptWidthUint32) && (Address & 0x03)) + return EFI_INVALID_PARAMETER; + + AddressCount = ValueSize * ( ((Width & ~3) != EfiBootScriptWidthFifoUint8 ) ? Count : 1); + +#if 0 //<-----For PCI-Express + if (Address & 0xffffffff00000000) //Extended register? + { + if (Address & 0xfffff00000000000) return EFI_INVALID_PARAMETER; //Limit 4k + Register = (UINT16) (Address >> 16); + RegisterMax = 0x1000; + } else { +#else + Register = (UINT8) Address; + RegisterMax = 0x100; +#endif +#if 0 + } +#endif + + //---Validate Inputs--- + if (!Count) return EFI_INVALID_PARAMETER; + + if (Register + AddressCount > RegisterMax) return EFI_INVALID_PARAMETER; + + + //---Fill and Copy Table--- + Ptr = AllocTableEntry((UINT32)sizeof(BOOT_SCRIPT_WRITE_PCI) + AddressCount); + if (Ptr == 0) return EFI_OUT_OF_RESOURCES; + + WritePci.Type = (UINT16) TABLE_TYPE2(EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE,Width); + WritePci.Address = Address; + WritePci.Count = Count; + + MemCpy(Ptr, &WritePci, sizeof(BOOT_SCRIPT_WRITE_PCI)); //Use MemCpy to avoid alignment problems. + Ptr = (UINT8*) Ptr + sizeof(BOOT_SCRIPT_WRITE_PCI); + + MemCpy(Ptr, Buffer, AddressCount); + + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: BootScriptPciReadWrite +// +// Description: Write to boot script table an PciReadWrite. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN va_list arglist +// +// Output: +// EFI_STATUS +// +// Notes: +// Here is the control flow of this function: +// 1. Get variable argument list from stack. +// 2. Validate argument list. If invalid return EFI_INVALID_PARAMETER; +// 3. Allocate entry from table. If no room in table, return EFI_OUT_OF_RESOURCES. +// 4. Fill fixed table entries. +// 5. Return EFI_SUCCESS. +// +//--------------------------------------------------------------------------- +// +EFI_STATUS BootScriptPciReadWrite ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + va_list arglist + ) +{ + EFI_BOOT_SCRIPT_WIDTH Width = va_arg(arglist, EFI_BOOT_SCRIPT_WIDTH); + UINT64 Address = va_arg(arglist, UINT64); + VOID *Data = va_arg(arglist, VOID *); + VOID *DataMask = va_arg(arglist, VOID *); + + BOOT_SCRIPT_READ_WRITE_PCI ReadWritePci; + VOID *Ptr; + UINT8 ValueSize = (UINT8) (1 << (Width & 3)); + UINT64 BitMask; + UINT16 Register; + UINT16 RegisterMax; + if (((Width & 3) == EfiBootScriptWidthUint16) && (Address & 0x01)) + return EFI_INVALID_PARAMETER; + if (((Width & 3) >= EfiBootScriptWidthUint32) && (Address & 0x03)) + return EFI_INVALID_PARAMETER; + + switch(Width&3) + { + case EfiBootScriptWidthUint8: BitMask = 0x00000000000000ff; break; + case EfiBootScriptWidthUint16: BitMask = 0x000000000000ffff; break; + case EfiBootScriptWidthUint32: BitMask = 0x00000000ffffffff; break; + default: BitMask = 0xffffffffffffffff; + } + +#if 0 //<-----For PCI-Express + if (Address & 0xffffffff00000000) //Extended register? + { + if (Address & 0xfffff00000000000) return EFI_INVALID_PARAMETER; //Limit 4k + Register = (UINT16) (Address >> 16); + RegisterMax = 0x1000; + } else { +#else + Register = (UINT8) Address; + RegisterMax = 0x100; +#endif +#if 0 + } +#endif + + //---Validate Inputs--- + if (Register + ValueSize > RegisterMax) return EFI_INVALID_PARAMETER; + + + //---Fill and Copy Table--- + Ptr = AllocTableEntry(sizeof(BOOT_SCRIPT_READ_WRITE_PCI)); + if (Ptr == 0) return EFI_OUT_OF_RESOURCES; + + ReadWritePci.Type = (UINT16) TABLE_TYPE2(EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE, Width); + ReadWritePci.Address = Address; + ReadWritePci.Value = *(UINT64*) Data & BitMask; + ReadWritePci.Mask = *(UINT64*) DataMask & BitMask; + + MemCpy(Ptr, &ReadWritePci, sizeof(BOOT_SCRIPT_READ_WRITE_PCI)); //Use MemCpy to avoid alignment problems. + + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: BootScriptSmbusExecute +// +// Description: Write to boot script table an SmbusExecute. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN va_list arglist +// +// Output: +// EFI_STATUS +// +//--------------------------------------------------------------------------- +// +EFI_STATUS BootScriptSmbusExecute ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + va_list arglist + ) +{ + VOID *Ptr; + VOID *Buffer; + + BOOT_SCRIPT_SMBUS_EXECUTE_32 Smbus; + + Smbus.Type = TABLE_TYPE1(EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE); + Smbus.SlaveAddress = (UINT32)va_arg(arglist, UINTN); + Smbus.Command = (UINT32)va_arg(arglist, UINTN); + Smbus.Operation = va_arg(arglist, EFI_SMBUS_OPERATION); + Smbus.PecCheck = va_arg(arglist, BOOLEAN); + Smbus.Length = *(va_arg(arglist, UINTN*)); + + Buffer = va_arg(arglist, VOID*); + + Ptr = AllocTableEntry(sizeof(BOOT_SCRIPT_SMBUS_EXECUTE_32) + (UINT32)Smbus.Length); + if (Ptr == 0) return EFI_OUT_OF_RESOURCES; + + MemCpy(Ptr, &Smbus, sizeof(BOOT_SCRIPT_SMBUS_EXECUTE_32)); //Use MemCpy to avoid alignment problems. + Ptr = (UINT8*) Ptr + sizeof(BOOT_SCRIPT_SMBUS_EXECUTE_32); + + MemCpy(Ptr, Buffer, (UINT32)Smbus.Length); + + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: BootScriptStall +// +// Description: Write to boot script table an Stall. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN va_list arglist +// +// Output: +// EFI_STATUS +// +//--------------------------------------------------------------------------- +// +EFI_STATUS BootScriptStall ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + va_list arglist + ) +{ + VOID *Ptr; + BOOT_SCRIPT_STALL Stall; + + Ptr = AllocTableEntry(sizeof(BOOT_SCRIPT_STALL)); + if (Ptr == 0) return EFI_OUT_OF_RESOURCES; + + Stall.Type = TABLE_TYPE1(EFI_BOOT_SCRIPT_STALL_OPCODE); + Stall.Duration = va_arg(arglist, UINTN); + + MemCpy(Ptr, &Stall, sizeof(BOOT_SCRIPT_STALL)); + + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: BootScriptIoPoll +// +// Description: Write to boot script table a IoPoll (OEM specific). +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN va_list arglist +// +// Output: +// EFI_STATUS +// +//--------------------------------------------------------------------------- +// +EFI_STATUS BootScriptIoPoll ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + va_list arglist + ) +{ + EFI_BOOT_SCRIPT_WIDTH Width = va_arg(arglist, EFI_BOOT_SCRIPT_WIDTH); + UINT64 Address = va_arg(arglist, UINT64); + VOID *DataMask = va_arg(arglist, VOID *); + VOID *DataResult = va_arg(arglist, VOID *); + + BOOT_SCRIPT_POLL_IO PollIo; + VOID *Ptr; + UINT8 ValueSize = (UINT8) (1 << (Width & 3)); + UINT64 BitMask; + UINT64 Mask, Result; + + Mask = *(UINT64*)DataMask; + Result = *(UINT64*)DataResult; + + switch(Width&3) + { + case EfiBootScriptWidthUint8: BitMask = 0x00000000000000ff; break; + case EfiBootScriptWidthUint16: BitMask = 0x000000000000ffff; break; + case EfiBootScriptWidthUint32: BitMask = 0x00000000ffffffff; break; + default: BitMask = 0xffffffffffffffff; + } + + //---Validate Inputs--- + if (Address + ValueSize > 0xffff) return EFI_INVALID_PARAMETER; + + + //---Fill and Copy Table--- + Ptr = AllocTableEntry(sizeof(BOOT_SCRIPT_POLL_IO)); + if (Ptr == 0) return EFI_OUT_OF_RESOURCES; + + PollIo.Type = (UINT16) TABLE_TYPE2(EFI_BOOT_SCRIPT_IO_POLL_OPCODE_OEM, Width); + PollIo.Port = (UINT16) Address; + PollIo.Mask = Mask & BitMask; + PollIo.Result = Result & BitMask; + + MemCpy(Ptr, &PollIo, sizeof(BOOT_SCRIPT_POLL_IO)); //Use MemCpy to avoid alignment problems. + + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: BootScriptMemPoll +// +// Description: Write to boot script table a MemPoll. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN va_list arglist +// +// Output: +// EFI_STATUS +// +//--------------------------------------------------------------------------- +// +EFI_STATUS BootScriptMemPoll ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + va_list arglist + ) +{ + EFI_BOOT_SCRIPT_WIDTH Width = va_arg(arglist, EFI_BOOT_SCRIPT_WIDTH); + UINT64 Address = va_arg(arglist, UINT64); + VOID *DataMask = va_arg(arglist, VOID *); + VOID *DataResult = va_arg(arglist, VOID *); + + BOOT_SCRIPT_POLL_MEM PollMem; + VOID *Ptr; + UINT8 ValueSize = (UINT8) (1 << (Width & 3)); + UINT64 BitMask; + UINT64 Mask, Result; + + Mask = *(UINT64*)DataMask; + Result = *(UINT64*)DataResult; + + switch(Width&3) + { + case EfiBootScriptWidthUint8: BitMask = 0x00000000000000ff; break; + case EfiBootScriptWidthUint16: BitMask = 0x000000000000ffff; break; + case EfiBootScriptWidthUint32: BitMask = 0x00000000ffffffff; break; + default: BitMask = 0xffffffffffffffff; + } + + //---Validate Inputs--- +#if defined(EFI64) || defined(EFIx64) + if (Address + ValueSize < Address) return EFI_INVALID_PARAMETER; //Overflow +#else + Address &= 0xffffffff; //When UINT32 -> UINT64, compiler sometimes sign extends. + if (Address + ValueSize > 0xffffffff) return EFI_INVALID_PARAMETER; +#endif + + //---Fill and Copy Table--- + Ptr = AllocTableEntry(sizeof(BOOT_SCRIPT_POLL_MEM)); + if (Ptr == 0) return EFI_OUT_OF_RESOURCES; + + PollMem.Type = (UINT16) TABLE_TYPE2(EFI_BOOT_SCRIPT_MEM_POLL_OPCODE_OEM, Width); + PollMem.Address = (UINT64)Address; + PollMem.Mask = Mask & BitMask; + PollMem.Result = Result & BitMask; + + MemCpy(Ptr, &PollMem, sizeof(BOOT_SCRIPT_POLL_MEM)); //Use MemCpy to avoid alignment problems. + + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: BootScriptPciPoll +// +// Description: Write to boot script table an PciPoll. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN va_list arglist +// +// Output: +// EFI_STATUS +// +// Notes: +// Here is the control flow of this function: +// 1. Get variable argument list from stack. +// 2. Validate argument list. If invalid return EFI_INVALID_PARAMETER; +// 3. Allocate entry from table. If no room in table, return EFI_OUT_OF_RESOURCES. +// 4. Fill fixed table entries. +// 5. Return EFI_SUCCESS. +// +//--------------------------------------------------------------------------- +// +EFI_STATUS BootScriptPciPoll ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + va_list arglist + ) +{ + EFI_BOOT_SCRIPT_WIDTH Width = va_arg(arglist, EFI_BOOT_SCRIPT_WIDTH); + UINT64 Address = va_arg(arglist, UINT64); + VOID *DataMask = va_arg(arglist, VOID *); + VOID *DataResult= va_arg(arglist, VOID *); + + BOOT_SCRIPT_POLL_PCI PollPci; + VOID *Ptr; + UINT8 ValueSize = (UINT8) (1 << (Width & 3)); + UINT64 BitMask; + UINT16 Register; + UINT16 RegisterMax; + + switch(Width&3) + { + case EfiBootScriptWidthUint8: BitMask = 0x00000000000000ff; break; + case EfiBootScriptWidthUint16: BitMask = 0x000000000000ffff; break; + case EfiBootScriptWidthUint32: BitMask = 0x00000000ffffffff; break; + default: BitMask = 0xffffffffffffffff; + } + +#if 0 //<-----For PCI-Express + if (Address & 0xffffffff00000000) //Extended register? + { + if (Address & 0xfffff00000000000) return EFI_INVALID_PARAMETER; //Limit 4k + Register = (UINT16) (Address >> 16); + RegisterMax = 0x1000; + } else { +#else + Register = (UINT8) Address; + RegisterMax = 0x100; +#endif +#if 0 + } +#endif + + //---Validate Inputs--- + if (Register + ValueSize > RegisterMax) return EFI_INVALID_PARAMETER; + + //---Fill and Copy Table--- + Ptr = AllocTableEntry(sizeof(BOOT_SCRIPT_POLL_PCI)); + if (Ptr == 0) return EFI_OUT_OF_RESOURCES; + + PollPci.Type = (UINT16) TABLE_TYPE2(EFI_BOOT_SCRIPT_PCI_POLL_OPCODE_OEM, Width); + PollPci.Address = Address; + PollPci.Mask = *(UINT64*) DataMask & BitMask; + PollPci.Result = *(UINT64*) DataResult & BitMask; + + MemCpy(Ptr, &PollPci, sizeof(BOOT_SCRIPT_POLL_PCI)); //Use MemCpy to avoid alignment problems. + + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: BootScriptDispatch +// +// Description: Write to boot script table an Dispatch. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN va_list arglist +// +// Output: +// EFI_STATUS +// +//--------------------------------------------------------------------------- +// +EFI_STATUS BootScriptDispatch ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + va_list arglist + ) +{ +//---------Unsupported by now------------------------ + + VOID *Ptr; + BOOT_SCRIPT_DISPATCH Dispatch; + + Ptr = AllocTableEntry(sizeof(BOOT_SCRIPT_DISPATCH)); + if (Ptr == 0) return EFI_OUT_OF_RESOURCES; + + Dispatch.Type = TABLE_TYPE1(EFI_BOOT_SCRIPT_DISPATCH_OPCODE); + Dispatch.EntryPoint = va_arg(arglist, EFI_PHYSICAL_ADDRESS); + + MemCpy(Ptr, &Dispatch, sizeof(BOOT_SCRIPT_DISPATCH)); + + return EFI_SUCCESS; + +// return EFI_UNSUPPORTED; +} +#if PI_SPECIFICATION_VERSION>=0x0001000A +// +//--------------------------------------------------------------------------- +// +// Procedure: SaveStateDispatch2 +// +// Description: Write to boot script table an Dispatch2. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN va_list arglist +// +// Output: +// EFI_STATUS +// +//--------------------------------------------------------------------------- +// +EFI_STATUS SaveStateDispatch2 ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + va_list arglist + ) +{ + VOID *Ptr; + BOOT_SCRIPT_DISPATCH2 Dispatch2; + + Ptr = AllocTableEntry(sizeof(BOOT_SCRIPT_DISPATCH2)); + if (Ptr == 0) return EFI_OUT_OF_RESOURCES; + + Dispatch2.Type = TABLE_TYPE1(EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE); + Dispatch2.EntryPoint = va_arg(arglist, EFI_PHYSICAL_ADDRESS); + Dispatch2.Context = va_arg(arglist, EFI_PHYSICAL_ADDRESS); + + MemCpy(Ptr, &Dispatch2, sizeof(BOOT_SCRIPT_DISPATCH2)); + + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SaveStateInformation +// +// Description: Write to boot script table an Information entry. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN va_list arglist +// +// Output: +// EFI_STATUS +// +//--------------------------------------------------------------------------- +// +EFI_STATUS SaveStateInformation ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + va_list arglist + ) +{ + UINT32 InfoSize = va_arg(arglist, UINT32); + EFI_PHYSICAL_ADDRESS InfoBuffer = va_arg(arglist, EFI_PHYSICAL_ADDRESS); + BOOT_SCRIPT_INFORMATION Information; + VOID *Ptr; + + + Ptr = AllocTableEntry(sizeof(BOOT_SCRIPT_INFORMATION)); + if (Ptr == NULL) return EFI_OUT_OF_RESOURCES; + + Information.Type = TABLE_TYPE1(EFI_BOOT_SCRIPT_INFORMATION_OPCODE); + Information.Size = InfoSize; + Information.MessagePtr = InfoBuffer; + + MemCpy(Ptr, &Information, sizeof(BOOT_SCRIPT_INFORMATION)); + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SaveStatePciCfg2Write +// +// Description: Write to boot script table an PciWrite. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN va_list arglist +// +// Output: +// EFI_STATUS +// +// Notes: +// Here is the control flow of this function: +// 1. Get variable argument list from stack. +// 2. Validate argument list. If invalid return EFI_INVALID_PARAMETER; +// 3. Allocate entry from table. If no room in table, return EFI_OUT_OF_RESOURCES. +// 4. Fill fixed table entries. +// 5. Add data to end of fixed table. +// 6. Return EFI_SUCCESS. +// +//--------------------------------------------------------------------------- +// +EFI_STATUS SaveStatePciCfg2Write ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + va_list arglist + ) +{ + EFI_BOOT_SCRIPT_WIDTH Width = va_arg(arglist, EFI_BOOT_SCRIPT_WIDTH); + UINT16 Segment = va_arg(arglist, UINT16); + UINT64 Address = va_arg(arglist, UINT64); + UINTN Count = va_arg(arglist, UINTN); + VOID *Buffer = va_arg(arglist, VOID*); + + BOOT_SCRIPT_PCI_CFG2_WRITE WritePci; + VOID *Ptr; + UINT8 ValueSize = (UINT8) (1 << (Width & 3)); + UINTN AddressCount; + UINT16 Register; + UINT16 RegisterMax; + if (((Width & 3) == EfiBootScriptWidthUint16) && (Address & 0x01)) + return EFI_INVALID_PARAMETER; + if (((Width & 3) >= EfiBootScriptWidthUint32) && (Address & 0x03)) + return EFI_INVALID_PARAMETER; + + AddressCount = ValueSize * ( ((Width & ~3) != EfiBootScriptWidthFifoUint8 ) ? Count : 1); + +#if 0 //<-----For PCI-Express + if (Address & 0xffffffff00000000) //Extended register? + { + if (Address & 0xfffff00000000000) return EFI_INVALID_PARAMETER; //Limit 4k + Register = (UINT16) (Address >> 16); + RegisterMax = 0x1000; + } else { +#else + Register = (UINT8) Address; + RegisterMax = 0x100; +#endif +#if 0 + } +#endif + + //---Validate Inputs--- + if (!Count) return EFI_INVALID_PARAMETER; + + if (Register + AddressCount > RegisterMax) return EFI_INVALID_PARAMETER; + + + //---Fill and Copy Table--- + Ptr = AllocTableEntry((UINT32)sizeof(BOOT_SCRIPT_PCI_CFG2_WRITE) + AddressCount); + if (Ptr == 0) return EFI_OUT_OF_RESOURCES; + + WritePci.Type = (UINT16) TABLE_TYPE2(EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE,Width); + WritePci.Segment = Segment; + WritePci.Address = Address; + WritePci.Count = Count; + + MemCpy(Ptr, &WritePci, sizeof(BOOT_SCRIPT_PCI_CFG2_WRITE)); //Use MemCpy to avoid alignment problems. + Ptr = (UINT8*) Ptr + sizeof(BOOT_SCRIPT_PCI_CFG2_WRITE); + + MemCpy(Ptr, Buffer, AddressCount); + + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SaveStatePciCfg2ReadWrite +// +// Description: Write to boot script table an PciReadWrite. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN va_list arglist +// +// Output: +// EFI_STATUS +// +// Notes: +// Here is the control flow of this function: +// 1. Get variable argument list from stack. +// 2. Validate argument list. If invalid return EFI_INVALID_PARAMETER; +// 3. Allocate entry from table. If no room in table, return EFI_OUT_OF_RESOURCES. +// 4. Fill fixed table entries. +// 5. Return EFI_SUCCESS. +// +//--------------------------------------------------------------------------- +// +EFI_STATUS SaveStatePciCfg2ReadWrite ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + va_list arglist + ) +{ + EFI_BOOT_SCRIPT_WIDTH Width = va_arg(arglist, EFI_BOOT_SCRIPT_WIDTH); + UINT16 Segment = va_arg(arglist, UINT16); + UINT64 Address = va_arg(arglist, UINT64); + VOID *Data = va_arg(arglist, VOID *); + VOID *DataMask = va_arg(arglist, VOID *); + + BOOT_SCRIPT_PCI_CFG2_READ_WRITE ReadWritePci; + VOID *Ptr; + UINT8 ValueSize = (UINT8) (1 << (Width & 3)); + UINT64 BitMask; + UINT16 Register; + UINT16 RegisterMax; + if (((Width & 3) == EfiBootScriptWidthUint16) && (Address & 0x01)) + return EFI_INVALID_PARAMETER; + if (((Width & 3) >= EfiBootScriptWidthUint32) && (Address & 0x03)) + return EFI_INVALID_PARAMETER; + + switch(Width&3) + { + case EfiBootScriptWidthUint8: BitMask = 0x00000000000000ff; break; + case EfiBootScriptWidthUint16: BitMask = 0x000000000000ffff; break; + case EfiBootScriptWidthUint32: BitMask = 0x00000000ffffffff; break; + default: BitMask = 0xffffffffffffffff; + } + +#if 0 //<-----For PCI-Express + if (Address & 0xffffffff00000000) //Extended register? + { + if (Address & 0xfffff00000000000) return EFI_INVALID_PARAMETER; //Limit 4k + Register = (UINT16) (Address >> 16); + RegisterMax = 0x1000; + } else { +#else + Register = (UINT8) Address; + RegisterMax = 0x100; +#endif +#if 0 + } +#endif + + //---Validate Inputs--- + if (Register + ValueSize > RegisterMax) return EFI_INVALID_PARAMETER; + + + //---Fill and Copy Table--- + Ptr = AllocTableEntry(sizeof(BOOT_SCRIPT_PCI_CFG2_READ_WRITE)); + if (Ptr == 0) return EFI_OUT_OF_RESOURCES; + + ReadWritePci.Type = (UINT16) TABLE_TYPE2(EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE, Width); + ReadWritePci.Segment = Segment; + ReadWritePci.Address = Address; + ReadWritePci.Value = *(UINT64*) Data & BitMask; + ReadWritePci.Mask = *(UINT64*) DataMask & BitMask; + + MemCpy(Ptr, &ReadWritePci, sizeof(BOOT_SCRIPT_PCI_CFG2_READ_WRITE)); //Use MemCpy to avoid alignment problems. + + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SaveStateIoPoll +// +// Description: Write to boot script table a PI 1.1 IoPoll. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN va_list arglist +// +// Output: +// EFI_STATUS +// +//--------------------------------------------------------------------------- +// +EFI_STATUS SaveStateIoPoll ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + va_list arglist + ) +{ + EFI_BOOT_SCRIPT_WIDTH Width = va_arg(arglist, EFI_BOOT_SCRIPT_WIDTH); + UINT64 Address = va_arg(arglist, UINT64); + VOID *DataResult = va_arg(arglist, VOID *); + VOID *DataMask = va_arg(arglist, VOID *); + UINT64 Delay = va_arg(arglist, UINT64); + + BOOT_SCRIPT_IO_POLL IoPoll; + VOID *Ptr; + UINT8 ValueSize = (UINT8) (1 << (Width & 3)); + UINT64 BitMask; + UINT64 Mask, Result; + + Mask = *(UINT64*)DataMask; + Result = *(UINT64*)DataResult; + + switch(Width&3) + { + case EfiBootScriptWidthUint8: BitMask = 0x00000000000000ff; break; + case EfiBootScriptWidthUint16: BitMask = 0x000000000000ffff; break; + case EfiBootScriptWidthUint32: BitMask = 0x00000000ffffffff; break; + default: BitMask = 0xffffffffffffffff; + } + + //---Validate Inputs--- + if (Address + ValueSize > 0xffff) return EFI_INVALID_PARAMETER; + + + //---Fill and Copy Table--- + Ptr = AllocTableEntry(sizeof(BOOT_SCRIPT_IO_POLL)); + if (Ptr == 0) return EFI_OUT_OF_RESOURCES; + + IoPoll.Type = (UINT16) TABLE_TYPE2(EFI_BOOT_SCRIPT_IO_POLL_OPCODE, Width); + IoPoll.Port = (UINT16) Address; + IoPoll.Mask = Mask & BitMask; + IoPoll.Result = Result & BitMask; + IoPoll.Delay = Delay; + + MemCpy(Ptr, &IoPoll, sizeof(BOOT_SCRIPT_IO_POLL)); //Use MemCpy to avoid alignment problems. + + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SaveStateMemPoll +// +// Description: Write to boot script table a MemPoll (PI 1.1). +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN va_list arglist +// +// Output: +// EFI_STATUS +// +//--------------------------------------------------------------------------- +// +EFI_STATUS SaveStateMemPoll ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + va_list arglist + ) +{ + EFI_BOOT_SCRIPT_WIDTH Width = va_arg(arglist, EFI_BOOT_SCRIPT_WIDTH); + UINT64 Address = va_arg(arglist, UINT64); + VOID *DataMask = va_arg(arglist, VOID *); + VOID *DataResult = va_arg(arglist, VOID *); + UINT64 Delay = va_arg(arglist, UINT64); + UINT64 LoopTimes = va_arg(arglist, UINT64); + + BOOT_SCRIPT_MEM_POLL MemPoll; + VOID *Ptr; + UINT8 ValueSize = (UINT8) (1 << (Width & 3)); + UINT64 BitMask; + UINT64 Mask, Result; + + Mask = *(UINT64*)DataMask; + Result = *(UINT64*)DataResult; + + switch(Width&3) + { + case EfiBootScriptWidthUint8: BitMask = 0x00000000000000ff; break; + case EfiBootScriptWidthUint16: BitMask = 0x000000000000ffff; break; + case EfiBootScriptWidthUint32: BitMask = 0x00000000ffffffff; break; + default: BitMask = 0xffffffffffffffff; + } + + //---Validate Inputs--- +#if defined(EFI64) || defined(EFIx64) + if (Address + ValueSize < Address) return EFI_INVALID_PARAMETER; //Overflow +#else + Address &= 0xffffffff; //When UINT32 -> UINT64, compiler sometimes sign extends. + if (Address + ValueSize > 0xffffffff) return EFI_INVALID_PARAMETER; +#endif + + //---Fill and Copy Table--- + Ptr = AllocTableEntry(sizeof(BOOT_SCRIPT_MEM_POLL)); + if (Ptr == 0) return EFI_OUT_OF_RESOURCES; + + MemPoll.Type = (UINT16) TABLE_TYPE2(EFI_BOOT_SCRIPT_MEM_POLL_OPCODE, Width); + MemPoll.Address = (UINT64)Address; + MemPoll.Mask = Mask & BitMask; + MemPoll.Result = Result & BitMask; + MemPoll.Delay = Delay; + MemPoll.LoopTimes= LoopTimes; + MemCpy(Ptr, &MemPoll, sizeof(BOOT_SCRIPT_MEM_POLL)); //Use MemCpy to avoid alignment problems. + //TRACE((-1,"SaveState Mem poll Mask %lx\n", MemPoll.Mask)); + //TRACE((-1,"SaveState Mem poll Result %lx\n", MemPoll.Result)); + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SaveStatePciCfgPoll +// +// Description: Write to boot script table an PciPoll (PI 1.1). +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN va_list arglist +// +// Output: +// EFI_STATUS +// +// Notes: +// Here is the control flow of this function: +// 1. Get variable argument list from stack. +// 2. Validate argument list. If invalid return EFI_INVALID_PARAMETER; +// 3. Allocate entry from table. If no room in table, return EFI_OUT_OF_RESOURCES. +// 4. Fill fixed table entries. +// 5. Return EFI_SUCCESS. +// +//--------------------------------------------------------------------------- +// +EFI_STATUS SaveStatePciCfgPoll ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + va_list arglist + ) +{ + EFI_BOOT_SCRIPT_WIDTH Width = va_arg(arglist, EFI_BOOT_SCRIPT_WIDTH); + UINT64 Address = va_arg(arglist, UINT64); + VOID *DataResult= va_arg(arglist, VOID *); + VOID *DataMask = va_arg(arglist, VOID *); + UINT64 Delay = va_arg(arglist, UINT64); + + BOOT_SCRIPT_PCI_CFG_POLL PciPoll; + VOID *Ptr; + UINT8 ValueSize = (UINT8) (1 << (Width & 3)); + UINT64 BitMask; + UINT16 Register; + UINT16 RegisterMax; + + switch(Width&3) + { + case EfiBootScriptWidthUint8: BitMask = 0x00000000000000ff; break; + case EfiBootScriptWidthUint16: BitMask = 0x000000000000ffff; break; + case EfiBootScriptWidthUint32: BitMask = 0x00000000ffffffff; break; + default: BitMask = 0xffffffffffffffff; + } + +#if 0 //<-----For PCI-Express + if (Address & 0xffffffff00000000) //Extended register? + { + if (Address & 0xfffff00000000000) return EFI_INVALID_PARAMETER; //Limit 4k + Register = (UINT16) (Address >> 16); + RegisterMax = 0x1000; + } else { +#else + Register = (UINT8) Address; + RegisterMax = 0x100; +#endif +#if 0 + } +#endif + + //---Validate Inputs--- + if (Register + ValueSize > RegisterMax) return EFI_INVALID_PARAMETER; + + //---Fill and Copy Table--- + Ptr = AllocTableEntry(sizeof(BOOT_SCRIPT_PCI_CFG_POLL)); + if (Ptr == 0) return EFI_OUT_OF_RESOURCES; + + PciPoll.Type = (UINT16) TABLE_TYPE2(EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE, Width); + PciPoll.Address = Address; + PciPoll.Mask = *(UINT64*) DataMask & BitMask; + PciPoll.Result = *(UINT64*) DataResult & BitMask; + PciPoll.Delay = Delay; + + MemCpy(Ptr, &PciPoll, sizeof(BOOT_SCRIPT_PCI_CFG_POLL)); //Use MemCpy to avoid alignment problems. + + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SaveStatePciCfg2Poll +// +// Description: Write to boot script table an PciPoll Cfg2 (PI 1.1). +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN va_list arglist +// +// Output: +// EFI_STATUS +// +// Notes: +// Here is the control flow of this function: +// 1. Get variable argument list from stack. +// 2. Validate argument list. If invalid return EFI_INVALID_PARAMETER; +// 3. Allocate entry from table. If no room in table, return EFI_OUT_OF_RESOURCES. +// 4. Fill fixed table entries. +// 5. Return EFI_SUCCESS. +// +//--------------------------------------------------------------------------- +// +EFI_STATUS SaveStatePciCfg2Poll ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + va_list arglist + ) +{ + EFI_BOOT_SCRIPT_WIDTH Width = va_arg(arglist, EFI_BOOT_SCRIPT_WIDTH); + UINT16 Segment = va_arg(arglist, UINT16); + UINT64 Address = va_arg(arglist, UINT64); + VOID *DataResult= va_arg(arglist, VOID *); + VOID *DataMask = va_arg(arglist, VOID *); + UINT64 Delay = va_arg(arglist, UINT64); + + BOOT_SCRIPT_PCI_CFG2_POLL PciPoll2; + VOID *Ptr; + UINT8 ValueSize = (UINT8) (1 << (Width & 3)); + UINT64 BitMask; + UINT16 Register; + UINT16 RegisterMax; + + switch(Width&3) + { + case EfiBootScriptWidthUint8: BitMask = 0x00000000000000ff; break; + case EfiBootScriptWidthUint16: BitMask = 0x000000000000ffff; break; + case EfiBootScriptWidthUint32: BitMask = 0x00000000ffffffff; break; + default: BitMask = 0xffffffffffffffff; + } + +#if 0 //<-----For PCI-Express + if (Address & 0xffffffff00000000) //Extended register? + { + if (Address & 0xfffff00000000000) return EFI_INVALID_PARAMETER; //Limit 4k + Register = (UINT16) (Address >> 16); + RegisterMax = 0x1000; + } else { +#else + Register = (UINT8) Address; + RegisterMax = 0x100; +#endif +#if 0 + } +#endif + + //---Validate Inputs--- + if (Register + ValueSize > RegisterMax) return EFI_INVALID_PARAMETER; + + //---Fill and Copy Table--- + Ptr = AllocTableEntry(sizeof(BOOT_SCRIPT_PCI_CFG2_POLL)); + if (Ptr == 0) return EFI_OUT_OF_RESOURCES; + + PciPoll2.Type = (UINT16) TABLE_TYPE2(EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE , Width); + PciPoll2.Segment = Segment; + PciPoll2.Address = Address; + PciPoll2.Mask = *(UINT64*) DataMask & BitMask; + PciPoll2.Result = *(UINT64*) DataResult & BitMask; + PciPoll2.Delay = Delay; + + MemCpy(Ptr, &PciPoll2, sizeof(BOOT_SCRIPT_PCI_CFG2_POLL)); //Use MemCpy to avoid alignment problems. + + return EFI_SUCCESS; +} +#endif //#if PI_SPECIFICATION_VERSION>=0x0001000A +GENERIC_OPCODE_FUNC OpCodeFuncs[] = +{ + BootScriptIoWrite, //0 + BootScriptIoReadWrite, //1 + BootScriptMemWrite, //2 + BootScriptMemReadWrite, //3 + BootScriptPciWrite, //4 + BootScriptPciReadWrite, //5 + BootScriptSmbusExecute, //6 + BootScriptStall, //7 + BootScriptDispatch, //8 +#if PI_SPECIFICATION_VERSION>=0x0001000A + SaveStateDispatch2, //9 + SaveStateInformation, //a ->0xA + SaveStatePciCfg2Write, //b ->0xB + SaveStatePciCfg2ReadWrite, //c ->0xC + SaveStateIoPoll, //d + SaveStateMemPoll, //e + SaveStatePciCfgPoll, //f + SaveStatePciCfg2Poll, //10 +#endif +//oem + BootScriptIoPoll, //0x80 -> + BootScriptMemPoll, //0x81 -> + BootScriptPciPoll, //0x82 -> +}; + +// +//--------------------------------------------------------------------------- +// +// Procedure: EfiBootScriptWrite +// +// Description: All boot script functions (except close table) call this function. +// This function passes argument list to appropriate function. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN UINT16 OpCode +// ... +// +// Output: +// EFI_STATUS +// +//--------------------------------------------------------------------------- +// +EFI_STATUS EfiBootScriptWrite ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + IN UINT16 TableName, + IN UINT16 OpCode, + ... + ) +{ + EFI_STATUS Status; + va_list arglist; + va_start(arglist, OpCode); + + if (TableName != EFI_ACPI_S3_RESUME_SCRIPT_TABLE) + return EFI_INVALID_PARAMETER; + + if (OpCode > 0x82) { + Status = EFI_INVALID_PARAMETER; goto EXIT_BOOT_SCRIPT_WRITE; + } + +#if PI_SPECIFICATION_VERSION>=0x0001000A + if (OpCode > 16 && OpCode < 0x80) {Status = EFI_INVALID_PARAMETER; goto EXIT_BOOT_SCRIPT_WRITE;} +#else + if (OpCode > 8 && OpCode < 0x80) {Status = EFI_INVALID_PARAMETER; goto EXIT_BOOT_SCRIPT_WRITE;} +#endif + + if (OpCode >= 0x80) + { + OpCode -= (0x80 - 9); +#if PI_SPECIFICATION_VERSION>=0x0001000A + OpCode += 8; +#endif + } + + Status = OpCodeFuncs[OpCode](This, arglist); + +EXIT_BOOT_SCRIPT_WRITE: + va_end(arglist); + return Status; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: EfiBootScriptCloseTable +// +// Description: Save table in runtime closing table and return pointer to table. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// OUT EFI_PHYSICAL_ADDRESS *Address +// +// Output: +// EFI_STATUS +// +// Referrals: +// +// Notes: +// Here is the control flow of this function: +// 1. Allocate table entry for BOOT_SCRIPT_TABLE_END. If no entry, return EFI_OUT_OF_RESOURCES. +// 2. Fill table. +// 3. Allocate space for new table in Runtime. +// 4. Copy table to new table. +// 5. Set *Address to Runtime Table. +// 6. Free old table. +// 7. Create a initial table to start over if more Scripts are added. +// 8. Return EFI_SUCCESS. +// +//--------------------------------------------------------------------------- +// +EFI_STATUS EfiBootScriptCloseTable ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + IN UINT16 TableName, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +{ + TABLE_INFO *Info = gTableInfo; + UINTN TableLength; +//--------------------------------------- + if (TableName != EFI_ACPI_S3_RESUME_SCRIPT_TABLE) + return EFI_INVALID_PARAMETER; + TableLength = (UINTN)Info->TablePtr - (UINTN)Info->TableBottom +#if PI_SPECIFICATION_VERSION>=0x0001000A + + sizeof(BOOT_SCRIPT_INFO_STRUCTURE) +#endif + + (UINTN) sizeof(BOOT_SCRIPT_TABLE_END); + + //Copy to new table. + *Address = 0xFFFFFFFF; + if (pBS->AllocatePages(AllocateMaxAddress, EfiReservedMemoryType, + EFI_SIZE_TO_PAGES(TableLength + INIT_TABLE_SIZE) + 1, Address) != EFI_SUCCESS) + return EFI_OUT_OF_RESOURCES; + + MemCpy((VOID*)(UINTN)*Address,Info->TableBottom, TableLength); + pBS->FreePool(Info->TableBottom); + + //Reasign Table Address; + Info->TableBottom = (VOID*)(UINTN)*Address; + Info->TablePtr = (VOID*)((UINTN) Info->TableBottom + TableLength +#if PI_SPECIFICATION_VERSION>=0x0001000A + - sizeof(BOOT_SCRIPT_INFO_STRUCTURE) +#endif + - (UINTN) sizeof(BOOT_SCRIPT_TABLE_END)); + Info->TableSize = EFI_PAGES_TO_SIZE(EFI_SIZE_TO_PAGES(TableLength + INIT_TABLE_SIZE) + 1); + Info->WasClosed = TRUE; + + return EFI_SUCCESS; +} + +EFI_BOOT_SCRIPT_SAVE_PROTOCOL gBootScriptSaveProtocol = +{ + EfiBootScriptWrite, + EfiBootScriptCloseTable +}; + + +//PI 1.1 ++ +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A) + +VOID ClearInsertInfo() +{ + gInsertInfo.IsItInsert = FALSE; + gInsertInfo.BeforeOrAfter = FALSE; + gInsertInfo.Position = -1; + return; +} +// +//--------------------------------------------------------------------------- +// +// Procedure: SaveStateWrite +// +// Description: This function is used to store an OpCode to be replayed as part +// of the S3 resume boot path. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN UINT16 OpCode +// ... +// +// Output: +// EFI_STATUS +// +//--------------------------------------------------------------------------- +// +EFI_STATUS SaveStateWrite( + IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This, + IN UINT16 OpCode, + ...) +{ + EFI_STATUS Status=EFI_SUCCESS; + UINTN OpIndex; + va_list arglist; + va_start(arglist, OpCode); +//---------------------------------- + + //map SaveState opcodes to the op code table. + switch(OpCode){ + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 0x9: + case 0xA: + case 0xB: + case 0xC: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + OpIndex=OpCode; + break; + case 0x80: + case 0x81: + case 0x82: + OpIndex= OpCode - (0x6F); + break; + default: + Status = EFI_UNSUPPORTED; + goto EXIT_BOOT_SCRIPT_WRITE; + } + Status = OpCodeFuncs[OpIndex](&gBootScriptSaveProtocol, arglist); + //TRACE((-1,"SaveState UniqueIndex %x\n", gTableInfo->NumTableEntries -1)); + +EXIT_BOOT_SCRIPT_WRITE: + va_end(arglist); + return Status; +} +// +//--------------------------------------------------------------------------- +// +// Procedure: SaveStateInsert +// +// Description: This function is used to store an OpCode to be replayed as part +// of the S3 resume boot path. The opcode is stored before (TRUE) +// or after (FALSE) the position in the boot script table specified +// by Position. If Position is NULL or points to NULL then the new +// opcode is inserted at the beginning of the table (if TRUE) or end +// of the table (if FALSE). +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN BOOLEAN BeforeOrAfter +// IN OUT EFI_S3_BOOT_SCRIPT_POSITION *Position OPTIONAL +// IN UINT16 OpCode +// ... +// +// Output: +// EFI_STATUS +// +//--------------------------------------------------------------------------- +// +EFI_STATUS SaveStateInsert( + IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This, + IN BOOLEAN BeforeOrAfter, + IN OUT EFI_S3_BOOT_SCRIPT_POSITION *Position OPTIONAL, + IN UINT16 OpCode, + ... +){ + + EFI_STATUS Status=EFI_SUCCESS; + UINTN OpIndex; + + va_list arglist; + va_start(arglist, OpCode); +//---------------------------------- + + //map SaveState opcodes to the op code table. + switch(OpCode){ + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 0x9: + case 0xA: + case 0xB: + case 0xC: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + OpIndex=OpCode; + break; + case 0x80: + case 0x81: + case 0x82: + OpIndex= OpCode - (0x6F); + break; + default: + Status = EFI_INVALID_PARAMETER; + goto EXIT_BOOT_SCRIPT_WRITE; + } + + gInsertInfo.IsItInsert = TRUE; + gInsertInfo.BeforeOrAfter = BeforeOrAfter; + if (!Position || !*Position) + if (BeforeOrAfter) gInsertInfo.Position = -1; + else gInsertInfo.IsItInsert = FALSE; + else + { + if ((UINTN) *Position >= gTableInfo->NumTableEntries) + { + ClearInsertInfo(); + return EFI_INVALID_PARAMETER; + } + gInsertInfo.Position = (UINTN)*Position; + } + Status = OpCodeFuncs[OpIndex](&gBootScriptSaveProtocol, arglist); + if (Position) *Position = (VOID*)(gTableInfo->NumTableEntries - 1); + ClearInsertInfo(); +EXIT_BOOT_SCRIPT_WRITE: + va_end(arglist); + return Status; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SaveStateLabel +// +// Description: Find a label within the boot script table and, if not present, +// optionally create it. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN BOOLEAN BeforeOrAfter +// IN BOOLEAN CreateIfNotFound +// IN OUT EFI_S3_BOOT_SCRIPT_POSITION *Position OPTIONAL +// IN CONST CHAR8 *Label +// +// Output: +// EFI_STATUS +// +//--------------------------------------------------------------------------- +// +EFI_STATUS SaveStateLabel( + IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This, + IN BOOLEAN BeforeOrAfter, + IN BOOLEAN CreateIfNotFound, + IN OUT EFI_S3_BOOT_SCRIPT_POSITION *Position OPTIONAL, + IN CONST CHAR8 *Label) +{ + UINT32 LabelSize, i; + UINT8 *TableHdr = gTableInfo->TableBottom, *TableInfo; + UINT16 Type; + BOOT_SCRIPT_LABEL LabelStr; + + if ((Label == NULL) || (*Label == 0)) + { + TRACE((-1,"First Exit\n")); + return EFI_INVALID_PARAMETER; + } + for(LabelSize=0; LabelSize<= LABEL_MAX_SIZE ; LabelSize++) + { + if (Label[LabelSize] == 0) break; // We assume label is 0 terminated. + + } + if (LabelSize >= LABEL_MAX_SIZE) + { + TRACE((-1,"2-d Exit\n")); + return EFI_INVALID_PARAMETER; // Label is too long or wrong/corrupted pointer + } + for (i=0; i<=gTableInfo->NumTableEntries; i++) + { + TableInfo = TableHdr + sizeof(BOOT_SCRIPT_INFO_STRUCTURE); + Type = *(UINT8*) TableInfo + (*((UINT8*) TableInfo + 1) << 8); //In case not aligned if alignment required. + if (Type == EFI_BOOT_SCRIPT_LABEL_OPCODE_OEM) + { + if (((BOOT_SCRIPT_LABEL*) TableInfo)->Size == LabelSize && + !MemCmp((VOID*)Label, TableInfo + sizeof(BOOT_SCRIPT_LABEL), LabelSize)) + { + if (Position) *Position = ((VOID*)((BOOT_SCRIPT_INFO_STRUCTURE*) TableHdr)->UniqueIndex); + else return EFI_INVALID_PARAMETER; //We found label, but can't return its position + return EFI_SUCCESS; // Label found and position returned + } + } + TableHdr += ((BOOT_SCRIPT_INFO_STRUCTURE*) TableHdr)->Length; + } + //----Label was not found + + if (!CreateIfNotFound) return EFI_NOT_FOUND; + + //----So - lets create it at position + + if (Position && ((UINTN) *Position >= gTableInfo->NumTableEntries)) + return EFI_INVALID_PARAMETER; // Position is not valid + + //---Filling gInsertInfo based on passed parameters + + gInsertInfo.IsItInsert = TRUE; + gInsertInfo.BeforeOrAfter = BeforeOrAfter; + + if (!Position || !*Position) + if (BeforeOrAfter) gInsertInfo.Position = -1; + else gInsertInfo.IsItInsert = FALSE; + else + { + if ((UINTN) *Position >= gTableInfo->NumTableEntries) + { + ClearInsertInfo(); + return EFI_INVALID_PARAMETER; + } + gInsertInfo.Position = (UINTN)*Position; + } + TableHdr = AllocTableEntry(sizeof(BOOT_SCRIPT_LABEL) + LabelSize); + ClearInsertInfo(); + if (!TableHdr) + return EFI_OUT_OF_RESOURCES; + LabelStr.Type = TABLE_TYPE1(EFI_BOOT_SCRIPT_LABEL_OPCODE_OEM); + LabelStr.Size = LabelSize; + MemCpy(TableHdr, &LabelStr, sizeof(BOOT_SCRIPT_LABEL)); + TableHdr += sizeof(BOOT_SCRIPT_LABEL); + MemCpy(TableHdr, (VOID*)Label, LabelSize); + if (Position) + *Position = (VOID*)(gTableInfo->NumTableEntries - 1); + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SaveStateCompare +// +// Description: Compare two positions in the boot script table and return their +// relative position. +// +// Input: +// IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This +// IN EFI_S3_BOOT_SCRIPT_POSITION Position1 +// IN EFI_S3_BOOT_SCRIPT_POSITION Position2 +// OUT UINTN *RelativePosition +// +// Output: +// EFI_STATUS +// +//--------------------------------------------------------------------------- +// +EFI_STATUS SaveStateCompare( + IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This, + IN EFI_S3_BOOT_SCRIPT_POSITION Position1, + IN EFI_S3_BOOT_SCRIPT_POSITION Position2, + OUT UINTN *RelativePosition) +{ + VOID *First, *Second; + if (((UINTN) Position1 > gTableInfo->NumTableEntries) + || ((UINTN) Position2 > gTableInfo->NumTableEntries)) + return EFI_INVALID_PARAMETER; + gInsertInfo.BeforeOrAfter = TRUE; + gInsertInfo.Position = (UINTN)Position1; + First = InsertPositionInBootScript (0); + if (!First) + { + ClearInsertInfo(); + return EFI_INVALID_PARAMETER; + } + gInsertInfo.Position = (UINTN)Position2; + Second = InsertPositionInBootScript (0); + if (!Second) + { + ClearInsertInfo(); + return EFI_INVALID_PARAMETER; + } + if (First == Second) *RelativePosition = 0; + else + if (First < Second) *RelativePosition = -1; + else *RelativePosition = 1; + ClearInsertInfo(); + return EFI_SUCCESS; +} + + + +EFI_S3_SAVE_STATE_PROTOCOL gS3SaveStateProtocol={ + SaveStateWrite, + SaveStateInsert, + SaveStateLabel, + SaveStateCompare +}; + +// +//--------------------------------------------------------------------------- +// +// Procedure: InitBootScriptSmm +// +// Description: Initialize table, if not done yet, and install protocols in SMM. +// +// Input: +// IN EFI_HANDLE ImageHandle +// IN EFI_SYSTEM_TABLE *SystemTable +// +// Output: +// EFI_STATUS +// +//--------------------------------------------------------------------------- +// + +EFI_STATUS InitBootScriptSmm( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; +//------------------------------- + Status=InitAmiSmmLib(ImageHandle, SystemTable); + ASSERT_EFI_ERROR (Status); + if(EFI_ERROR(Status)) return Status; + + Status=InitBootScriptStructure(TRUE); + if(EFI_ERROR(Status)) return Status; + + // We are in SMM, retrieve the pointer to SMM System Table + Status=mInternalSmmBase2->GetSmstLocation (mInternalSmmBase2, &gSmst2); + ASSERT (gSmst2 != NULL); + if( EFI_ERROR(Status) || (gSmst2 == NULL)) return EFI_UNSUPPORTED; + + + // Install SMM PCI Root Bridge I/O Protocol + Status=gSmst2->SmmInstallProtocolInterface( + &mSmmS3SaveHandle, + &gEfiS3SmmSaveStateProtocolGuid, + EFI_NATIVE_INTERFACE, + (EFI_S3_SMM_SAVE_STATE_PROTOCOL*)&gS3SaveStateProtocol + ); + + + + + return Status; + + +} + +#endif +//PI 1.1 -- + +// +//--------------------------------------------------------------------------- +// +// Procedure: InitBootScriptDxe +// +// Description: Initialize table and install protocols outside SMM. +// +// Input: +// IN EFI_HANDLE ImageHandle +// IN EFI_SYSTEM_TABLE *SystemTable +// +// Output: +// EFI_STATUS +// +//--------------------------------------------------------------------------- +// +EFI_STATUS InitBootScriptDxe( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = InitBootScriptStructure(FALSE); + if(EFI_ERROR(Status)) return Status; + + Status = SystemTable->BootServices->InstallMultipleProtocolInterfaces( + &ImageHandle, + &gEfiBootScriptSaveGuid, &gBootScriptSaveProtocol, +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A) + &gEfiS3SaveStateProtocolGuid, &gS3SaveStateProtocol, +#endif + NULL + ); + + ASSERT_EFI_ERROR(Status); + + Status = CreateReadyToBootEvent( + TPL_CALLBACK, + CallbackReadyToBoot, + NULL, + &gEvtReadyToBoot + ); + ASSERT_EFI_ERROR(Status); + + return Status; +} +// +//--------------------------------------------------------------------------- +// +// Procedure: InitBootScript +// +// Description: Initialize table and install protocols. +// Called twice - in and outside SMM. +// +// Input: +// IN EFI_HANDLE ImageHandle +// IN EFI_SYSTEM_TABLE *SystemTable +// +// Output: +// EFI_STATUS +// +//--------------------------------------------------------------------------- +// +EFI_STATUS InitBootScript( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ +#if PI_SPECIFICATION_VERSION>=0x0001000A + EFI_STATUS Status; + BOOLEAN InSmm=FALSE; +#endif + +//------- + InitAmiLib(ImageHandle, SystemTable); +//PI 1.1 ++ +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A) + // Retrieve SMM Base2 Protocol, Do not use gBS from UefiBootServicesTableLib on purpose + // to prevent inclusion of gBS, gST, and gImageHandle from SMM Drivers unless the + // SMM driver explicity declares that dependency. + Status = SystemTable->BootServices->LocateProtocol ( + &gEfiSmmBase2ProtocolGuid, + NULL, + (VOID **)&mInternalSmmBase2 + ); + if( EFI_ERROR(Status)){ + //if we can't find SMM Protocols that's not InSmm initialization + if(Status==EFI_NOT_FOUND) InSmm=FALSE; + else return EFI_UNSUPPORTED; + } else mInternalSmmBase2->InSmm (mInternalSmmBase2, &InSmm); + + // Check to see if we are already in SMM + if (!InSmm ) { +#endif + // We are not in SMM, so SMST is not needed + return InitBootScriptDxe(ImageHandle,SystemTable); +//PI 1.1 ++ +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A) + } else { + return InitBootScriptSmm(ImageHandle,SystemTable); + } +#endif +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** -- cgit v1.2.3