BayTrail/AmiCompatibilityPkg/Library/AcpiRes.c
2018-06-21 15:06:56 +08:00

2255 lines
62 KiB
C

//*************************************************************************
//*************************************************************************
//** **
//** (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/Library/AcpiRes.c 31 11/15/11 11:59a Felixp $
//
// $Revision: 31 $
//
// $Date: 11/15/11 11:59a $
//*************************************************************************
//<AMI_FHDR_START>
//
// Name: AcpiRes.c
//
// Description:
// Implementation of ASL MACROs for ResourceTemplate. See ACPI 2.0
// specification section 16.2.4.
//
//<AMI_FHDR_END>
//*************************************************************************
#include <AmiDxeLib.h>
#include <AcpiRes.h>
#include <Protocol/AcpiSystemDescriptionTable.h>
#include <Protocol/AcpiSupport.h>
// ===========================
// In Aptio4, these are externals defined in the AmiProtocolLib.
// In AptioV, there is no AmiProtocolLib.
// We could've listed these in AmiDxeLib.inf, but may break the
// build of some of the Aptio4 modules due to multiple defined symbols.
static EFI_GUID gLocalEfiAcpiSdtProtocolGuid = EFI_ACPI_SDT_PROTOCOL_GUID;
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: ASLM_IRQ
//
// Description:
// VOID* ASLM_IRQ(IN UINT8 dsc_cnt, IN UINT8 ll, IN UINT8 he,
// IN UINT8 shr, IN ...) generates a short IRQ descriptor and returns its
// address. User is responsible for freeing the returned memory.
//
// Input:
// IN UINT8 dsc_cnt
// Number of IRQ numbers in the list.
//
// IN UINT8 ll
// IRQ flag. 0 = active-high, 1 = active-low.
//
// IN UINT8 he
// IRQ flag. 0 = level-triggered, 1 = edge-triggered.
//
// IN UINT8 shr
// IRQ flag. 0 = not interrupt shareable, 1 = interrupt shareable.
//
// IN ...
// List of IRQ numbers. Valid values: 0-15.
//
// Output:
// VOID* address of the created IRQ descriptor. User is responsible for
// freeing the returned memory.
//
// Modified:
//
// Referrals:
// Malloc
// VA_START
// VA_ARG
// VA_END
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
VOID *ASLM_IRQ(UINT8 dsc_cnt, UINT8 ll, UINT8 he, UINT8 shr, ... )
{
UINT8 i;
UINT16 irq=0;
VA_LIST marker;
UINT32 sz=sizeof(ASLR_IRQ);
ASLR_IRQ *rb=(ASLR_IRQ*)Malloc(sz);
//------------------------------
if (!rb)return NULL;
pBS->SetMem(rb,sz,0);
//Update descriptor Header
rb->Hdr.Length=3;//sizeof(ASLR_IRQ)-sizeof(ASLRF_S_HDR);
rb->Hdr.Name=ASLV_RT_IRQ;
rb->Hdr.Type=ASLV_SMALL_RES;
//Update descriptor Body
rb->Flags._LL=ll;
rb->Flags._HE=he;
rb->Flags._SHR=shr;
VA_START(marker, shr);
for (i=0; i<dsc_cnt; i++)
{
irq|=(1<<VA_ARG(marker, UINT8));
}
VA_END(marker);
rb->_INT=irq;
return rb;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: ASLM_IRQNoFlags
//
// Description:
// VOID* ASLM_IRQNoFlags(IN UINT8 dsc_cnt, IN ...) generates a short IRQ
// descriptor without an optional IRQ information byte and returns its
// address. User is responsible for freeing the returned memory.
//
// Input:
// IN UINT8 dsc_cnt
// Number of IRQ numbers in the list.
//
// IN ...
// List of IRQ numbers. Valid values: 0-15.
//
// Output:
// VOID* address of the created IRQ descriptor. User is responsible for
// freeing the returned memory.
//
// Modified:
//
// Referrals:
// Malloc
// VA_START
// VA_ARG
// VA_END
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
VOID *ASLM_IRQNoFlags(UINT8 dsc_cnt, ... )
{
UINT8 i;
VA_LIST marker;
UINT16 irq=0;
UINT32 sz=sizeof(ASLR_IRQNoFlags);
ASLR_IRQNoFlags *rb=(ASLR_IRQNoFlags*)Malloc(sz);
//------------------------------
if (!rb)return NULL;
pBS->SetMem(rb,sz,0);
//Update descriptor Header
rb->Hdr.Length=2;//sizeof(ASLR_IRQNoFlags)-sizeof(ASLRF_S_HDR);
rb->Hdr.Name=ASLV_RT_IRQ;
rb->Hdr.Type=ASLV_SMALL_RES;
VA_START(marker, dsc_cnt);
for (i=0; i<dsc_cnt; i++)
{
irq|=(1<<VA_ARG(marker, UINT8));
}
VA_END(marker);
rb->_INT=irq;
return rb;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: ASLM_DMA
//
// Description:
// VOID* ASLM_DMA(IN UINT8 dsc_cnt, IN UINT8 typ, IN UINT8 bm, IN UINT8 siz,
// IN ...) generates a short DMA descriptor and returns its address. User is
// responsible for freeing the returned memory.
//
// Input:
// IN UINT8 dsc_cnt
// Number of channel numbers in the list.
//
// IN UINT8 typ
// DMA channel speed. Valid values are:
// ASLV_Compatibility, ASLV_TypeA, ASLV_TypeB, ASLV_TypeF
//
// IN UINT8 bm
// BusMaster or NotBusMaster. 0 defaults to BusMaster.
//
// IN UINT8 siz
// Transfer size. Valid values are:
// Transfer8, Transfer16, Transfer8_16
//
// IN ...
// List of channel numbers. Valid values are 0-7.
//
// Output:
// VOID* address of the created DMA descriptor. User is responsible for
// freeing the returned memory.
//
// Modified:
//
// Referrals:
// Malloc
// VA_START
// VA_ARG
// VA_END
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
VOID *ASLM_DMA(UINT8 dsc_cnt, UINT8 typ, UINT8 bm, UINT8 siz, ... )
{
UINT8 i, dma=0;
VA_LIST marker;
UINT32 sz=sizeof(ASLR_DMA);
ASLR_DMA *rb=(ASLR_DMA*)Malloc(sz);
//------------------------------
if (!rb)return NULL;
pBS->SetMem(rb,sz,0);
//Update descriptor Header
rb->Hdr.Length=sizeof(ASLR_DMA)-sizeof(ASLRF_S_HDR);
rb->Hdr.Name=ASLV_RT_DMA;
rb->Hdr.Type=ASLV_SMALL_RES;
//Update descriptor Body
rb->Flags._TYP=typ;
rb->Flags._BM=bm;
rb->Flags._SIZ=siz;
VA_START(marker, siz);
for (i=0; i<dsc_cnt; i++)
{
dma|=(1<<VA_ARG(marker, UINT8));
}
VA_END(marker);
rb->_DMA=dma;
return rb;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: ASLM_StartDependentFn
//
// Description:
// VOID* ASLM_StartDependentFn(IN UINT8 dsc_cnt, IN UINT8 pComp,
// IN UINT8 pPerf, IN ...) generates a Start-Dependent Function descriptor
// with the optional priority byte and returns its address. User is
// responsible for freeing the returned memory.
//
// Input:
// IN UINT8 dsc_cnt
// Number of items in the descriptor list.
//
// IN UINT8 pComp
// Compatibility priority. Valid values are 0-2.
//
// IN UINT8 pPerf
// Performance/robustness priority. Valid values are 0-2.
//
// IN ...
// List of descriptors for this dependent function.
//
// Output:
// VOID* address of the created Start-Dependent Function descriptor. User
// is responsible for freeing the returned memory.
//
// Modified:
//
// Referrals:
// MallocZ
// Malloc
// VA_START
// VA_ARG
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
VOID *ASLM_StartDependentFn(UINT8 dsc_cnt,UINT8 pComp,UINT8 pPerf, ...)
{
UINT8 i;
VA_LIST marker;
UINT32 sz=sizeof(EFI_ASL_DepFn)+sizeof(ASLR_StartDependentFn);
EFI_ASL_DepFn *rb=(EFI_ASL_DepFn*)MallocZ(sz);
//--------------------------------------------
if (!rb)return NULL;
rb->DepFn=(rb+1);
((ASLR_StartDependentFn*)rb->DepFn)->Hdr.Length=sizeof(ASLR_StartDependentFn)-sizeof(ASLRF_S_HDR);
((ASLR_StartDependentFn*)rb->DepFn)->Hdr.Name=ASLV_RT_StartDependentFn;
((ASLR_StartDependentFn*)rb->DepFn)->Hdr.Type=ASLV_SMALL_RES;
((ASLR_StartDependentFn*)rb->DepFn)->_PRI._CMP=pComp;
((ASLR_StartDependentFn*)rb->DepFn)->_PRI._PRF=pPerf;
rb->DepRes.Items=Malloc(sizeof(ASLR_HDR*)*dsc_cnt);
if (!rb->DepRes.Items) return NULL;
rb->DepRes.InitialCount=dsc_cnt;
rb->DepRes.ItemCount=dsc_cnt;
VA_START(marker, pPerf);
for (i=0; i<dsc_cnt; i++) rb->DepRes.Items[i]=VA_ARG(marker, VOID*);
return rb;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: ASLM_StartDependentFnNoPri
//
// Description:
// VOID* ASLM_StartDependentFnNoPri(IN UINT8 dsc_cnt, IN ...) generates a
// Start-Dependent Function descriptor without the optional priority byte and
// returns its address. User is responsible for freeing the returned memory.
//
// Input:
// IN UINT8 dsc_cnt
// Number of items in the descriptor list.
//
// IN ...
// List of descriptors for this dependent function.
//
// Output:
// VOID* address of the created Start-Dependent Function descriptor. User
// is responsible for freeing the returned memory.
//
// Modified:
//
// Referrals:
// MallocZ
// Malloc
// VA_START
// VA_ARG
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
VOID *ASLM_StartDependentFnNoPri(UINT8 dsc_cnt, ...)
{
UINT8 i;
VA_LIST marker;
UINT32 sz=sizeof(EFI_ASL_DepFn)+sizeof(ASLR_StartDependentFnNoPri);
EFI_ASL_DepFn *rb=(EFI_ASL_DepFn*)MallocZ(sz);
//--------------------------------------------
if (!rb)return NULL;
rb->DepFn=(rb+1);
((ASLR_StartDependentFnNoPri*)rb->DepFn)->Length=sizeof(ASLR_StartDependentFnNoPri)-sizeof(ASLRF_S_HDR);
((ASLR_StartDependentFnNoPri*)rb->DepFn)->Name=ASLV_RT_StartDependentFn;
((ASLR_StartDependentFnNoPri*)rb->DepFn)->Type=ASLV_SMALL_RES;
rb->DepRes.Items=Malloc(sizeof(ASLR_HDR*)*dsc_cnt);
if (!rb->DepRes.Items) return NULL;
rb->DepRes.InitialCount=dsc_cnt;
rb->DepRes.ItemCount=dsc_cnt;
VA_START(marker, dsc_cnt);
for (i=0; i<dsc_cnt; i++) rb->DepRes.Items[i]=VA_ARG(marker, VOID*);
return rb;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: ASLM_IO
//
// Description:
// VOID* ASLM_IO(IN UINT8 dec, IN UINT16 min, IN UINT16 max, IN UINT8 aln,
// IN UINT8 len) generates a short I/O descriptor and returns its address.
// User is responsible for freeing the returned memory.
//
// Input:
// IN UINT8 dec
// Decode value. Valid values are: ASLV_Decode16, ASLV_Decode10.
//
// IN UINT16 min
// Address minimum.
//
// IN UINT16 max
// Address maximum.
//
// IN UINT8 aln
// Base alignment.
//
// IN UINT8 len
// Range length.
//
// Output:
// VOID* address of the created I/O descriptor. User is responsible for
// freeing the returned memory.
//
// Modified:
//
// Referrals:
// MallocZ
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
VOID *ASLM_IO(UINT8 dec,UINT16 min,UINT16 max,UINT8 aln,UINT8 len)
{
ASLR_IO *rb=(ASLR_IO*)MallocZ(sizeof(ASLR_IO));
//------------------------------------------
if (!rb)return NULL;
rb->Hdr.Length=sizeof(ASLR_IO)-sizeof(ASLRF_S_HDR);
rb->Hdr.Name=ASLV_RT_IO;
rb->Hdr.Type=ASLV_SMALL_RES;
rb->_DEC=dec;
rb->_MIN=min;
rb->_MAX=max;
rb->_ALN=aln;
rb->_LEN=len;
return rb;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: ASLM_FixedIO
//
// Description:
// VOID* ASLM_FixedIO(IN UINT16 bas, IN UINT8 len) generates a short fixed
// I/O descriptor and returns its address. User is responible for freeing
// the returned memory.
//
// Input:
// IN UINT16 bas
// Address base.
//
// IN UINT8 len
// Range length.
//
// Output:
// VOID* address of the created fixed I/O descriptor. User is responsible
// for freeing the returned memory.
//
// Modified:
//
// Referrals:
// MallocZ
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
VOID *ASLM_FixedIO(UINT16 bas, UINT8 len)
{
ASLR_FixedIO *rb=(ASLR_FixedIO*)MallocZ(sizeof(ASLR_FixedIO));
//------------------------------------------
if (!rb)return NULL;
rb->Hdr.Length=sizeof(ASLR_FixedIO)-sizeof(ASLRF_S_HDR);
rb->Hdr.Name=ASLV_RT_FixedIO;
rb->Hdr.Type=ASLV_SMALL_RES;
rb->_BAS=bas;
rb->_LEN=len;
return rb;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: ASLM_VendorShort
//
// Description:
// VOID* ASLM_VendorShort(IN UINT8 byte_cnt, IN ...) generates a short
// Vendor-Defined descriptor and returns its address. User is responsible
// for freeing the returned memory.
//
// Input:
// IN UINT8 byte_cnt
// Number of bytes in the list. Must be less than 8.
//
// IN ...
// List of byte expressions for the descriptor. Must be less than 8
// elements.
//
// Output:
// VOID* address of the created Vendor-Defined descriptor. User is
// responsible for freeing the returned memory.
//
// Modified:
//
// Referrals:
// MallocZ
// VA_START
// VA_ARG
// VA_END
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
VOID *ASLM_VendorShort(UINT8 byte_cnt, ...)
{
UINT8 i;
VA_LIST marker;
UINT32 sz= sizeof(ASLR_VendorShort)+byte_cnt;
ASLR_VendorShort *rb=(ASLR_VendorShort*)MallocZ(sz);
UINT8 *bb=(UINT8*)rb+1;
//------------------------------
if (!rb)return NULL;
rb->Length=byte_cnt;
rb->Name=ASLV_RT_VendorShort;
rb->Type=ASLV_SMALL_RES;
VA_START(marker, byte_cnt);
//Update descriptor Body
for (i=0; i<byte_cnt; i++)bb[i]=VA_ARG(marker, UINT8);
VA_END(marker);
return rb;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: ASLM_Memory24
//
// Description:
// VOID* ASLM_Memory24(IN UINT8 rw, IN UINT8 min, IN UINT8 max,
// IN UINT8 aln, IN UINT8 len) generates a long 24-bit memory descriptor and
// returns its address. User is responsible for freeing the returned memory.
//
// Input:
// IN UINT8 rw
// Write protection flag. Valid values: ASLV_ReadOnly, ASLV_ReadWrite.
//
// IN UINT8 min
// Minimum base memory address [23:8].
//
// IN UINT8 max
// Maximum base memory address [23:8].
//
// IN UINT8 aln
// Base alignment.
//
// IN UINT8 len
// Range length.
//
// Output:
// VOID* address of the created long 24-bit memory descriptor. User is
// responsible for freeing the returned memory.
//
// Modified:
//
// Referrals:
// MallocZ
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
VOID *ASLM_Memory24(UINT8 rw,UINT8 min, UINT8 max, UINT8 aln, UINT8 len)
{
ASLR_Memory24 *rb=(ASLR_Memory24*)MallocZ(sizeof(ASLR_Memory24));
//------------------------------------------
if (!rb)return NULL;
rb->Hdr.Length=sizeof(ASLR_Memory24)-sizeof(ASLRF_S_HDR);
rb->Hdr.Name=ASLV_RT_Memory24;
rb->Hdr.Type=ASLV_SMALL_RES;
rb->_RW=rw;
rb->_MIN=min;
rb->_MAX=max;
rb->_ALN=aln;
rb->_LEN=len;
return rb;
}
//----------------------------------------------------------------------
// Methods Implementation for T_ITEM_LIST object
//----------------------------------------------------------------------
#define LST_INIT_COUNT 10 //initial value
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: reallocItemLst
//
// Description:
// EFI_STATUS reallocItemLst(IN T_ITEM_LIST *Lst) is an internal worker
// function which reallocates space for a T_ITEM_LIST.Items[] array.
//
// Input:
// IN T_ITEM_LIST *Lst
// List which needs its Items array reallocated.
//
// Output:
// EFI_OUT_OF_RESOURCES, if allocation failed.
// Otherwise, EFI_SUCCESS.
//
// Modified:
//
// Referrals:
// MallocZ
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
EFI_STATUS reallocItemLst(T_ITEM_LIST *Lst)
{
UINTN sz=0;
VOID *nrl=NULL; //new resource list pointer;
//---------------------------------------------
// if Initial count has not been initialized;
if (Lst->InitialCount==0) sz=LST_INIT_COUNT*sizeof(VOID*);
else
{
//or Initial Count was initialized but memory fot Items[] array was not allocated
if (Lst->InitialCount && !Lst->Items) sz=Lst->InitialCount*sizeof(VOID*);
else
{
//or if we at the end or near the end of the Items[] array list
if ((INTN)Lst->ItemCount > (INTN)(Lst->InitialCount-1))
sz=(Lst->InitialCount+LST_INIT_COUNT)*sizeof(VOID*);
}
}
if (sz)
{
nrl=MallocZ(sz);
if (!nrl) return EFI_OUT_OF_RESOURCES;
pBS->CopyMem((VOID*)nrl,(VOID*)Lst->Items,sizeof(VOID*)*Lst->ItemCount);
//Free Buffer of previouse ChildList...
pBS->FreePool((VOID*)Lst->Items);
//Make it point to a new ChildList
Lst->Items=nrl;
Lst->InitialCount=sz/sizeof(VOID*);
}
return EFI_SUCCESS;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: InsertItemLst
//
// Description:
// EFI_STATUS InsertItemLst(IN T_ITEM_LIST *Lst, IN VOID *pRes,
// IN UINTN ItemIndex) inserts the provided item pointed to by pRes into the
// provided Lst at index ItemIndex.
//
// Input:
// IN T_ITEM_LIST *Lst
// List to be inserted into.
//
// IN VOID *pRes
// Pointer to object to place in list.
//
// IN UINTN ItemIndex
// Index in list to place the object pointed to by pRes.
//
// Output:
// EFI_INVALID_PARAMETER, if the ItemIndex value is invalid.
// EFI_OUT_OF_RESOURCES, if there is not enough memory for the new object.
// Otherwise, EFI_SUCCESS.
//
// Modified:
//
// Referrals:
// reallocItemLst
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
EFI_STATUS InsertItemLst(T_ITEM_LIST *Lst, VOID* pRes, UINTN ItemIndex)
{
INTN i;
//----------------
if (!Lst->ItemCount && Lst->ItemCount<ItemIndex) return EFI_INVALID_PARAMETER;
//Check if Items[] array can accomodate a new child...
if (EFI_ERROR(reallocItemLst(Lst)))return EFI_OUT_OF_RESOURCES;
//Shift items after Index forward
for (i=(INTN)Lst->ItemCount-1; i>=(INTN)ItemIndex; i--) Lst->Items[i+1]=Lst->Items[i];
//fill Item address we are inserting
Lst->Items[ItemIndex]=pRes;
//Adjust Item Count
Lst->ItemCount++;
return EFI_SUCCESS;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: DeleteItemLst
//
// Description:
// EFI_STATUS DeleteItemLst(IN T_ITEM_LIST *Lst, IN UINTN ItemIndex,
// IN BOOLEAN FreeData) deletes the object stored at the provided ItemIndex
// in Lst. Frees the memory associated with the object pointer if FreeData
// is TRUE.
//
// Input:
// IN T_ITEM_LIST *Lst
// List to be deleted from.
//
// IN UINTN ItemIndex
// Index inside Lst->Items to be deleted.
//
// IN BOOLEAN FreeData
// TRUE will free the memory associated with the deleted object.
//
// Output:
// EFI_INVALID_PARAMETER, if the provided ItemIndex is invalid.
// Otherwise, EFI_SUCCESS.
//
// Modified:
//
// Referrals:
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
EFI_STATUS DeleteItemLst(T_ITEM_LIST *Lst, UINTN ItemIndex, BOOLEAN FreeData)
{
UINTN i;
//----------------
if (!Lst->ItemCount || Lst->ItemCount<=ItemIndex) return EFI_INVALID_PARAMETER;
//Free Data associated with Iterm if requested;
if (FreeData)pBS->FreePool(Lst->Items[ItemIndex]);
//Shift items after ItemIndex backwards
for (i=ItemIndex; i<Lst->ItemCount-1; i++) Lst->Items[i]=Lst->Items[i+1];
//Adjust Item Count
Lst->ItemCount--;
return EFI_SUCCESS;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: AppendItemLst
//
// Description:
// EFI_STATUS AppendItemLst(IN T_ITEM_LIST *Lst, IN VOID *pRes) appends the
// provided object to Lst.
//
// Input:
// IN T_ITEM_LIST *Lst
// List to be appended to.
//
// IN VOID *pRes
// Object to be appended.
//
// Output:
// EFI_OUT_OF_RESOURCES, if memory allocation fails.
// Otherwise, EFI_SUCCESS.
//
// Modified:
//
// Referrals:
// reallocItemLst
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
EFI_STATUS AppendItemLst(T_ITEM_LIST *Lst, VOID* pRes )
{
//Check if Items[] array can accomodate a new child...
if (EFI_ERROR(reallocItemLst(Lst)))return EFI_OUT_OF_RESOURCES;
Lst->Items[Lst->ItemCount]=pRes;
Lst->ItemCount++;
return EFI_SUCCESS;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: ClearItemLst
//
// Description:
// VOID ClearItemLst(IN T_ITEM_LIST *Lst, IN BOOLEAN FreeData) clears all
// the items of Lst. If FreeData is TRUE, frees all the memory associated
// with the stored objects.
//
// Input:
// IN T_ITEM_LIST *Lst
// List to be cleared.
//
// IN BOOLEAN FreeData
// If TRUE, all objects are freed.
//
// Output:
// VOID.
//
// Modified:
//
// Referrals:
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
VOID ClearItemLst(T_ITEM_LIST *Lst, BOOLEAN FreeData)
{
UINTN i;
//-----------------------------------------
if (FreeData)for (i=0; i<Lst->ItemCount; i++)
{
if (Lst->Items[i])pBS->FreePool(Lst->Items[i]);
}
if (Lst->Items) pBS->FreePool(Lst->Items);
Lst->Items=NULL;
Lst->ItemCount=0;
Lst->InitialCount=0;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: CopyItemLst
//
// Description:
// EFI_STATUS CopyItemLst(IN T_ITEM_LIST *Lst, OUT T_ITEM_LIST **NewLstPtr)
// copies Lst into a new list and provides the address of the copy in
// NewLstPtr.
//
// Input:
// IN T_ITEM_LIST *Lst
// List to be copied.
//
// OUT T_ITEM_LIST **NewLstPtr
// Location to store the address of the new copy.
//
// Output:
// EFI_OUT_OF_RESOURCES, if memory allocation fails.
// Otherwise, EFI_SUCCESS.
//
// Modified:
//
// Referrals:
// MallocZ
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
EFI_STATUS CopyItemLst(T_ITEM_LIST *Lst, T_ITEM_LIST **NewLstPtr)
{
UINTN i = 0;
T_ITEM_LIST *NewLst = NULL;
*NewLstPtr = NULL;
*NewLstPtr = MallocZ(sizeof(T_ITEM_LIST));
if (!*NewLstPtr)
{
return EFI_OUT_OF_RESOURCES;
}
NewLst = *NewLstPtr;
NewLst->InitialCount = Lst->InitialCount;
NewLst->ItemCount = Lst->ItemCount;
if (Lst->ItemCount == 0)
{
return EFI_SUCCESS;
}
NewLst->Items = MallocZ( Lst->ItemCount * sizeof(VOID*) );
if (!NewLst->Items)
{
return EFI_OUT_OF_RESOURCES;
}
for (i = 0; i < Lst->ItemCount; i++)
{
NewLst->Items[i] = NULL;
if (Lst->Items[i])
{
NewLst->Items[i] = MallocZ( sizeof(Lst->Items[i]) );
if (!NewLst->Items[i])
{
return EFI_OUT_OF_RESOURCES;
}
pBS->CopyMem(NewLst->Items[i], Lst->Items[i], sizeof(Lst->Items[i]));
}
}
return EFI_SUCCESS;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: ValidateDescriptor
//
// Description:
// BOOLEAN ValidateDescriptor(IN ASLR_QWORD_ASD *Descriptor,
// IN ASLR_TYPE_ENUM ResType, IN BOOLEAN Fixed) validates a ASLV_LARGE_RES
// descriptor.
//
// Input:
// IN ASLR_QWORD_ASD *Descriptor
// Descriptor to be validated.
//
// IN ASLR_TYPE_ENUM ResType
// The resource type of the descriptor. Valid values are:
// tResAll, tResIoMem, tResBus
//
// IN BOOLEAN Fixed
// If TRUE, checks the general flags for consistancy.
//
// Output:
// TRUE if a valid ASLR_QWORD_ASD descriptor. Otherwise, FALSE.
//
// Modified:
//
// Referrals:
//
// Notes:
// Helper function for ValidateDescriptorBlock.
//
//<AMI_PHDR_END>
//*************************************************************************
BOOLEAN ValidateDescriptor(ASLR_QWORD_ASD *Descriptor,ASLR_TYPE_ENUM ResType,BOOLEAN Fixed)
{
//Check ASL Resource Descriptor Header consistancy
if (
(Descriptor->Hdr.Name!=ASLV_RT_QWORD_ASD) ||
(Descriptor->Hdr.Type!=ASLV_LARGE_RES) ||
(Descriptor->Hdr.Length!=sizeof(ASLR_QWORD_ASD)-sizeof(ASLRF_L_HDR) )
)return FALSE;
//Check ASL Resource Descriptor General Flags Consistancy
if (Fixed)
{
if (
(!Descriptor->GFlags._MIF) ||
(!Descriptor->GFlags._MAF)
)return FALSE;
}
if (Descriptor->Type>2) return FALSE;
//Check ASL Resource Descriptor Resource Type
switch (ResType)
{
case tResBus:
if (Descriptor->Type!=ASLRV_SPC_TYPE_BUS) return FALSE;
if ((Descriptor->_MIN+Descriptor->_LEN)>0x100)return FALSE;
break;
case tResIoMem:
if (Descriptor->Type>=ASLRV_SPC_TYPE_BUS) return FALSE;
break;
case tResAll:
if (Descriptor->Type>ASLRV_SPC_TYPE_BUS) return FALSE;
break;
default : return FALSE;
}
return TRUE;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: ValidateDescriptorBlock
//
// Description:
// UINTN ValidateDescriptorBlock(IN ASLR_QWORD_ASD *DscStart,
// IN ASLR_TYPE_ENUM ResType, IN BOOLEAN Fixed) validates the consistancy of
// the provided ACPI QWORD resource descriptors block which contains some
// number of ASLR_QWORD_ASDs in memory terminated by an ASLR_EndTag. Returns
// the total size of the resource descriptors plus the size of the
// ASLR_EndTag.
//
// Input:
// IN ASLR_QWORD_ASD *DscStart
// Pointer to the first descriptor in the block to be validated.
//
// IN ASLR_TYPE_ENUM ResType
// The resource type of the descriptors. Valid values are:
// tResAll, tResIoMem, tResBus
//
// IN BOOLEAN Fixed
// If TRUE, checks the general flags for consistancy.
//
// Output:
// UINTN size of the resource descriptor block plus the size of the
// ASLR_EndTag.
//
// Modified:
//
// Referrals:
// ValidateDescriptor
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
UINTN ValidateDescriptorBlock(ASLR_QWORD_ASD* DscStart, ASLR_TYPE_ENUM ResType, BOOLEAN Fixed)
{
ASLR_QWORD_ASD *qwd=DscStart;
UINTN len=0;
ASLR_EndTag *endtag=(ASLR_EndTag*)DscStart;
//-----------------------------------
//resource descriptor is empty...
if (endtag->Hdr.HDR==ASLV_END_TAG_HDR) return sizeof(ASLR_EndTag);
while (endtag->Hdr.HDR!=ASLV_END_TAG_HDR)
{
if (!ValidateDescriptor(qwd, ResType, Fixed)) return 0;
else len+=sizeof(ASLR_QWORD_ASD);
qwd++;
endtag=(ASLR_EndTag*)qwd;
}
len+=sizeof(ASLR_EndTag);
return len;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: CheckDsdt
//
// Description:
// BOOLEAN CheckDsdt(IN ACPI_HDR *Dsdt) checks the signature of the provided
// ACPI header for the DSDT signature.
//
// Input:
// IN ACPI_HDR *Dsdt
// Pointer to the ACPI header to be checked for the DSDT signature.
//
// Output:
// TRUE if the header signature is that of the DSDT. Otherwise, FALSE.
//
// Modified:
//
// Referrals:
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
BOOLEAN CheckDsdt(ACPI_HDR *Dsdt)
{
if (Dsdt->Signature!=DSDT_SIG) return FALSE;
return TRUE;
}
// <AMI_PHDR_START>
//----------------------------------------------------------------------------
//
// Name: GetRbAmlPackagePointer
//
// Description:
// This function returns a pointer to a named AML Package object in the
// specified root bridge scope along with information necessary to
// dynamically read and/or modify its data.
//
// This function also serves as an example of how a named Package object
// pointer can be obtained, if the scope path is known.
//
// Input:
// IN ACPI_HDR **Dsdt
// - This pointer is either NULL or the pointer to the DSDT.
// (If it is NULL, LibGetDsdt is called to obtain the
// pointer.)
// IN CHAR8 *RbName
// - This string specifies the name of the root bridge
// device for which the Package object is to be found.
// IN CHAR8 *PackageName
// - This string specifies the name of the Package object
// to be found.
// OUT ASL_OBJ_INFO *Package
// - This parameter is updated to contain the address of
// the ASL_OBJ_INFO structure associated with the
// located Package object.
// OUT PACKAGE_ELEMENT *Elements
// - This parameter is updated to contain the address
// of the first element of the located Package object.
// OUT UINT8 *ElementCount
// - This parameter is updated to contain the number
// of elements in the located Package object.
//
// Output:
// EFI_STATUS (Return Value)
// = EFI_SUCCESS if successful
// = or valid EFI error code
//
// Modified:
// None
//
// Referrals:
// LibGetDsdt()
// GetAslObj()
//
// Notes:
// Package objects are aggregate arrays of elements that can be of
// different size and type. This function assumes the caller
// understands the structure of the package object associated with the
// PackageName paramenter and can iterate through the elements.
//
// Prototypes for several element types are provided in AcpiRes.h
// (see PACKAGE_ELEMENT). Additional types can be supported by
// typecasting PACKAGE_ELEMENT.Ptr.
//
// Example: Supported ASL Package Declarations (must be initialized)
//
// Scope(\_SB.PCI0) {
// Name (PAK1, Package ()
// {
// 0x0123,
// 0x0123,
// 0x0123,
// 0x0123,
// })
// }
//
// Scope(\_SB.PCI1) {
// Name (PAK1, Package ()
// {
// 0x0123,
// 0x0123,
// 0x0123,
// 0x0123,
// })
// }
//
// Example: Usage
//
// VOID Function(){
// ASL_OBJ_INFO Package;
// PACKAGE_ELEMENT Element;
// UINT8 ElementCount;
//
// Status = GetRbAmlPackagePointer( "PCI1", "PAK1",
// &Package, &Element, &ElementCount);
// ...
// }
//
//
//--------------------------------------------------------------------------
// <AMI_PHDR_END>
EFI_STATUS GetRbAmlPackagePointer(
IN ACPI_HDR **Dsdt,
IN CHAR8 *RbName,
IN CHAR8 *PackageName,
OUT ASL_OBJ_INFO *Package,
OUT PACKAGE_ELEMENT *Elements,
OUT UINT8 *ElementCount )
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS Address;
ASL_OBJ_INFO RbScope;
AML_PACKAGE_HEADER *Pkg;
if (*Dsdt == NULL){
Status = LibGetDsdt(&Address, EFI_ACPI_TABLE_VERSION_ALL);
if (EFI_ERROR(Status)) {
return Status;
}
else {
*Dsdt = (ACPI_HDR*)Address;
}
}
// Get a pointer to this root bridge's device scope
Status = GetAslObj( (UINT8*)(*Dsdt + 1),
(*Dsdt)->Length - sizeof(ACPI_HDR) - 1,
RbName,
otDevice,
&RbScope );
// Get a pointer to the AML Package object
if (!EFI_ERROR(Status)){
Status = GetAslObj( (UINT8*)RbScope.DataStart,
RbScope.Length,
PackageName,
otName,
Package );
}
// Parse the Package object to get a pointer to the first element and
// number of elements.
if (!EFI_ERROR(Status)){
Pkg = Package->DataStart;
// Check ByteCount to determine the encoding and obtain a pointer
// to the first element and the element count.
switch (Pkg->Encoding.Small.ByteCount) {
case 0:
(*Elements).Ptr = &Pkg->Encoding.Small.Element;
*ElementCount = Pkg->Encoding.Small.ElementCount;
break;
case 1:
(*Elements).Ptr = &Pkg->Encoding.Large1.Element;
*ElementCount = Pkg->Encoding.Large1.ElementCount;
break;
case 2:
(*Elements).Ptr = &Pkg->Encoding.Large2.Element;
*ElementCount = Pkg->Encoding.Large2.ElementCount;
break;
case 3:
(*Elements).Ptr = &Pkg->Encoding.Large3.Element;
*ElementCount = Pkg->Encoding.Large3.ElementCount;
}
}
return Status;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: GetPackageLen
//
// Description:
// UINTN GetPackageLen(IN AML_PACKAGE_LBYTE *Pck, OUT UINT8 *BytesCnt)
// determines the length in bytes of an AML package.
//
// Input:
// IN AML_PACKAGE_LBYTE *Pck
// AML package to be measured.
//
// OUT UINT8 *BytesCnt
// The ByteCount value of the package.
//
// Output:
// UINTN size of the AML package in bytes.
//
// Modified:
//
// Referrals:
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
//will determine length in bytes of a package
UINTN GetPackageLen(AML_PACKAGE_LBYTE *Pck, UINT8 *BytesCnt)
{
UINTN len=0;
UINT8 *p=(UINT8*)Pck;
//------------------
if (BytesCnt)*BytesCnt=0;
if (!Pck->ByteCount) len=Pck->Length;
else
{
len|=(Pck->Length&0x0F);
if (BytesCnt)*BytesCnt=Pck->ByteCount;
switch (Pck->ByteCount)
{
case 1:
{
UINT8 b=*(p+1);
len|=(b<<4);
} break;
case 2:
{
UINT16 w=(UINT16)(*((UINT16*)(p+1)));
len|=(w<<4);
} break;
case 3:
{
UINT32 d=(UINT32)(*((UINT32*)(p+1)));
d&=0xffffff;
len|=(d<<4);
} break;
} //switch
}
return len;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: ConvertAslName
//
// Description:
// UINT32 ConvertAslName(IN UINT8 *AslName) converts an ASL name into a
// UINT32 value and returns it.
//
// Input:
// IN UINT8 *AslName
// Pointer to the ASL name string.
//
// Output:
// UINT32 translation of the ASL name.
//
// Modified:
//
// Referrals:
// Strlen
// MemCpy
//
// Notes:
// Helper function for FindAslObjectName.
//
//<AMI_PHDR_END>
//*************************************************************************
UINT32 ConvertAslName(UINT8 *AslName)
{
AML_NAME_SEG n;
UINTN l=Strlen(AslName);
//-------------------------
n.NAME=0x5F5F5F5F;
MemCpy(&n.Name[0],AslName,l);
return n.NAME;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: FindAslObjectName
//
// Description:
// VOID* FindAslObjectName(IN UINT8 *Start, IN UINT8 *ObjName, IN UINTN Len)
// finds an ASL object by its name string and returns its location.
//
// Input:
// IN UINT8 *Start
// Location to begin scanning for the ASL object.
//
// IN UINT8 *ObjName
// Name of the ASL object to be located.
//
// IN UINTN Len
// Maximum length of bytes to scan for the ASL object.
//
// Output:
// VOID* pointer to the start of the ASL name string in memory.
//
// Modified:
//
// Referrals:
// ConvertAslName
//
// Notes:
// Helper function for GetAslObj.
//
//<AMI_PHDR_END>
//*************************************************************************
VOID* FindAslObjectName(UINT8 *Start, UINT8 *ObjName, UINTN Len)
{
unsigned int i;
UINT8 *p;
AML_NAME_SEG *obj,nm;
//------------------------------
nm.NAME=ConvertAslName(ObjName);
p=Start;
for (i=0; i<Len; i++)
{
obj=(AML_NAME_SEG*)(&p[i]);
if (obj->NAME!=nm.NAME)continue;
return &p[i];
}
return NULL;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: HideAslMethodFromOs
//
// Description:
// Destroys Method passed as MethodName parameter if it is present in ASL object
// described by AslObj parameter
//
// Input:
// IN ASL_OBJ_INFO *AslObj
// Pointer to ASL_OBJ_INFO structure, which discribes ASL object to modify
//
// UINT8 *MethodName
// Name of the ASL Method to be destroyed.
//
//
// Referrals:
// ConvertAslName
//
//<AMI_PHDR_END>
//*************************************************************************
VOID HideAslMethodFromOs (ASL_OBJ_INFO *AslObj, UINT8 *MethodName)
{
UINT32 AslMethodName = ConvertAslName(MethodName), i, Position; //*(UINT32*)MethodName
UINT8 *Start = AslObj->DataStart;
// TRACE ((-1,"AslMethodNameHex = %X, Str=%s; Start= %lX\n", AslMethodName, MethodName, (UINT64) Start));
for (i = 0; i < AslObj->Length; i++)
{
Position =*(UINT32*)(Start+i);
if (Position == AslMethodName)
// If method is found
{
// TRACE ((-1,"METHOD FOUND = %x,\n", Position));
Start[i] = 'X'; //Replace leading _ with X
return;
}
}
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: CheckOpCode
//
// Description:
// BOOLEAN CheckOpCode(IN UINT8 *NameStart, IN UINT8 OpCode,
// IN UINT8 ExtOpCode, OUT ASL_OBJ_INFO *ObjInfo) checks an ASL object for
// the user provided op code and extended op code and returns the op code
// location in a user allocated ASL_OBJ_INFO structure.
//
// Input:
// IN UINT8 *NameStart
// Pointer to the start of the ASL object's name.
//
// IN UINT8 OpCode
// Op code to be checked.
//
// IN UINT8 ExtOpCode
// Extended op code to be checked. If set as 0, only checks for OpCode.
//
// OUT ASL_OBJ_INFO *ObjInfo
// Pointer to a user allocated ASL_OBJ_INFO structure which will be updated
// with the associated information if the op codes are located. If an
// extended op code is specified, ObjInfo->Object is filled with the location
// of the extended op code; otherwise ObjInfo->Object refers to the location
// of the op code.
//
// Output:
// TRUE if the op code and extended op code (if specified) are located;
// otherwise, FALSE.
//
// Modified:
//
// Referrals:
// GetPackageLen
//
// Notes:
// Helper function for GetAslObj.
//
//<AMI_PHDR_END>
//*************************************************************************
BOOLEAN CheckOpCode(UINT8 *NameStart, UINT8 OpCode, UINT8 ExtOpCode, ASL_OBJ_INFO *ObjInfo)
{
UINT8 *p, *p1;
INTN i;
//---------------------
//Maximum number of bytes in PackageLength is 4
if ( (*(NameStart-1))==AML_PR_ROOT || (*(NameStart-1))==AML_PR_PARENT) NameStart--;
//if we Looking For ASL Name Object its a special case.
if (OpCode==AML_OP_NAME && !ExtOpCode)
{
p=NameStart-1;
if (*p==OpCode)
{
ObjInfo->Object=p;
ObjInfo->ObjName=NameStart;
ObjInfo->Length=0;
return TRUE;
}
return FALSE;
}
//if we Looking For ASL Name Object its a special case.
if (OpCode==AML_OP_OPREG && ExtOpCode)
{
p=NameStart-2;
if (*p==ExtOpCode && *(p+1)==OpCode)
{
ObjInfo->Object=p;
ObjInfo->ObjName=NameStart;
ObjInfo->Length=0;
return TRUE;
}
return FALSE;
}
for (i=2; i<6; i++)
{
p=NameStart-i;
if (ExtOpCode) p1=p-1;
else p1=NULL;
if (p1)if (*p1!=ExtOpCode) continue;
if (*p!=OpCode) continue;
if (p1)ObjInfo->Object=p1;
else ObjInfo->Object=p;
ObjInfo->Length=GetPackageLen((AML_PACKAGE_LBYTE*)(p+1),NULL);
ObjInfo->ObjName=NameStart;
return TRUE;
}
return FALSE;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: GetAslObj
//
// Description:
// EFI_STATUS GetAslObj(IN UINT8 *Start, IN UINTN Length, IN UINT8 *Name,
// IN ASL_OBJ_TYPE ObjType, OUT ASL_OBJ_INFO *ObjInfo)
//
// Input:
// IN UINT8 *Start
// Starting location in memory to begin scanning for the desired ASL object.
//
// IN UINTN Length
// Maximum number of bytes in memory to be scanned starting from Start for
// the ASL object.
//
// IN UINT8 *Name
// Pointer to the name of the ASL object to be located.
//
// IN ASL_OBJ_TYPE ObjType
// Type of the ASL object to be located. Supports: otScope, otName, otProc,
// otTermal, otDevice, otMethod, otPwrRes, otOpReg
//
// OUT ASL_OBJ_INFO *ObjInfo
// Returns completed ASL_OBJ_INFO structure, if the ASL object is found.
//
// Output:
// EFI_NOT_FOUND, if object not found or invalid type.
// Otherwise, EFI_SUCCESS.
//
// Modified:
//
// Referrals:
// FindAslObjectName
// CheckOpCode
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
//Since the search is done by locating the OBJECT name.
//Caller must know what ASL Object Type he is looking for.
EFI_STATUS GetAslObj(UINT8 *Start, UINTN Length, UINT8 *Name, ASL_OBJ_TYPE ObjType, ASL_OBJ_INFO *ObjInfo)
{
UINT8 *pn, *s, eop,op;
UINTN l, i;
BOOLEAN objfound=FALSE;
// ASL_OBJ_INFO objinf;
//---------------------------
//if(!CheckDsdt(PDsdt)) return FALSE;
//s=((UINT8*)PDsdt)+sizeof(ACPI_HDR);
s=Start;
//l=PDsdt->Length-sizeof(ACPI_HDR)-1;
l=Length;
while (!objfound)
{
pn=FindAslObjectName(s,Name,l);
if (!pn) return EFI_NOT_FOUND;
//If we found the name let's check if it is the Object we are looking for
//it could be just object referance, or field definition inside the object,
//or double name, or multiple name definition we must filter such situations
// and make sure we have got the actual object but not its reference instance
switch (ObjType)
{
case otScope :
i=0;
eop=0;
op=AML_OP_SCOPE;
break;
case otName :
i=0;
eop=0;
op=AML_OP_NAME;
break;
case otProc :
i=6;
eop=AML_PR_EXTOP;
op=AML_OP_PROC;
break;
case otTermal :
i=0;
eop=AML_PR_EXTOP;
op=AML_OP_THERMAL;
break;
case otDevice :
i=0;
eop=AML_PR_EXTOP;
op=AML_OP_DEVICE;
break;
case otMethod :
i=1;
eop=0;
op=AML_OP_METHOD;
break;
case otPwrRes :
i=3;
eop=AML_PR_EXTOP;
op=AML_OP_PWRRES;
break;
case otOpReg :
i=0;
eop=AML_PR_EXTOP;
op=AML_OP_OPREG;
break;
default: return EFI_NOT_FOUND;
} //switch
objfound=CheckOpCode(pn, op, eop, ObjInfo);
if (!objfound)
{
l-=(UINTN)(pn-s)-4;
s=pn+4;
continue;
}
ObjInfo->ObjType=ObjType;
ObjInfo->DataStart=pn+i+4;
return EFI_SUCCESS;
} //while ()
return EFI_NOT_FOUND;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: UpdateAslNameBuffer
//
// Description:
// EFI_STATUS UpdateAslNameBuffer(UINT8 *BufferStart, UINTN BufferLen,
// IN UINT8 *ObjName, IN UINT64 Value) locates an ASL object by its name,
// ObjName, in Memory Buffer specified by BufferStart, and BufferLen
// and updates its data start with the user provided Value.
//
// Input:
// IN UINT8 *BufferStart
// Pointer to the DSDT.
//
// UINTN BufferLen
// Length of the Buffer
//
// IN UINT8 *ObjName
// Name of the ASL object to be updated.
//
// IN UINT64 Value
// New value for the ASL object's data entry.
//
// Output:
// EFI_INVALID_PARAMETER, if the DSDT pointer, ObjName or Value are invalid.
// EFI_NOT_FOUND, if object specified by ObjName not present.
// Otherwise, EFI_SUCCESS.
//
// Modified:
//
// Referrals:
// GetAslObj
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
EFI_STATUS UpdateAslNameBuffer(UINT8 *BufferStart, UINTN BufferLen, UINT8 *ObjName, UINT64 Value)
{
EFI_STATUS Status;
ASL_OBJ_INFO obj;
//---------------
Status=GetAslObj(BufferStart,BufferLen, ObjName, otName, &obj);
if (EFI_ERROR(Status)) return Status;
switch (*((UINT8*)obj.DataStart))
{
case AML_PR_BYTE:
{
UINT8 *p = (UINT8*)((UINT8*)obj.DataStart+1);
//----------------------------------
*p=(UINT8)Value;
} break;
case AML_PR_WORD:
{
UINT16 *p = (UINT16*)((UINT8*)obj.DataStart+1);
//----------------------------------
*p=(UINT16)Value;
} break;
case AML_PR_DWORD:
{
UINT32 *p = (UINT32*)((UINT8*)obj.DataStart+1);
//----------------------------------
*p=(UINT32)Value;
} break;
case AML_PR_QWORD:
{
UINT64 *p = (UINT64*)((UINT8*)obj.DataStart+1);
//----------------------------------
*p=(UINT64)Value;
} break;
case AML_ZERO_OP: case AML_ONE_OP:
{
if ((Value == 0) || (Value == 1))
{
UINT8 *p = (UINT8*)((UINT8*)obj.DataStart);
*p = (UINT8)Value;
}
else
{
return EFI_INVALID_PARAMETER;
}
} break;
default:
{
return EFI_INVALID_PARAMETER;
}
}
return EFI_SUCCESS;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: UpdateAslNameOfDevice
//
// Description:
// EFI_STATUS UpdateAslNameOfDevice(IN ACPI_HDR *PDsdt, IN CHAR8 *DeviceName,
// CHAR8 *ObjName, IN UINT64 Value) locates an ASL Device Object by its name,
// DeviceName, and then In the scope of this Device Object, trys to locate a
// Name Object, ObjName, in the DSDT. If found it updates its data place holder
// with user provided Value.
//
// Input:
// IN ACPI_HDR *PDsdt
// Pointer to the DSDT.
//
// IN CHAR8 *DeviceName
// Name of the ASL Device object having in it's scope Name Object to be updated.
//
// IN CHAR8 *ObjName
// Name of the ASL Name Object to be updated.
//
// IN UINT64 Value
// New value for the ASL object's data entry.
//
// Output:
// EFI_INVALID_PARAMETER, if the DSDT pointer, ObjName or Value are invalid.
// EFI_NOT_FOUND, if object specified by Device Name Or ObjName not present.
// Otherwise, EFI_SUCCESS.
//
// Modified:
//
// Referrals:
// CheckDsdt
// GetAslObj
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
EFI_STATUS UpdateAslNameOfDevice(ACPI_HDR *PDsdt, CHAR8 *DeviceName, CHAR8 *ObjName, UINT64 Value)
{
EFI_STATUS Status;
ASL_OBJ_INFO obj;
//---------------
if (!CheckDsdt(PDsdt)) return EFI_INVALID_PARAMETER;
Status=GetAslObj((UINT8*)(PDsdt+1),PDsdt->Length-sizeof(ACPI_HDR)-1, DeviceName, otDevice, &obj);
if (EFI_ERROR(Status)) return Status;
Status=UpdateAslNameBuffer((UINT8*)obj.DataStart, obj.Length, ObjName, Value);
return Status;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: UpdateAslNameObject
//
// Description:
// EFI_STATUS UpdateAslNameObject(IN ACPI_HDR *PDsdt, IN UINT8 *ObjName,
// IN UINT64 Value) locates an ASL object by its name, ObjName, in the DSDT
// and updates its data start with the user provided Value.
//
// Input:
// IN ACPI_HDR *PDsdt
// Pointer to the DSDT.
//
// IN UINT8 *ObjName
// Name of the ASL object to be updated.
//
// IN UINT64 Value
// New value for the ASL object's data entry.
//
// Output:
// EFI_INVALID_PARAMETER, if the DSDT pointer, ObjName or Value are invalid.
// Otherwise, EFI_SUCCESS.
//
// Modified:
//
// Referrals:
// CheckDsdt
// GetAslObj
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
EFI_STATUS UpdateAslNameObject(ACPI_HDR *PDsdt, UINT8 *ObjName, UINT64 Value)
{
//------------------------------------
if (!CheckDsdt(PDsdt)) return EFI_INVALID_PARAMETER;
return UpdateAslNameBuffer((UINT8*)(PDsdt+1),PDsdt->Length-sizeof(ACPI_HDR)-1, ObjName, Value);
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: ChsumTbl
//
// Description:
// UINT8 ChsumTbl(IN UINT8 *TblStart, IN UINT32 BytesCount) calculates the
// checksum of a table starting at TblStart of length BytesCount and returns
// the checksum value.
//
// Input:
// IN UINT8 *TblStart
// Starting address of the memory area to checksum.
//
// IN UINT32 BytesCount
// Length in bytes of the memory area to checksum.
//
// Output:
// UINT8 checksum value starting from TblStart and ending at
// TblStart + BytesCount.
//
// Modified:
//
// Referrals:
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
UINT8 ChsumTbl(UINT8* TblStart, UINT32 BytesCount)
{
UINTN i;
UINT8 res=*TblStart;
for (i=1; i<BytesCount; i++) res+=TblStart[i];
res=0-res;
return(res);
} //checksum_table
static EFI_GUID gAmiIsaDmaIrqMaskVarGuid = AMI_IRQ_DMA_MASK_VARIABLE_GUID;
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: AmiIsaIrqMask
//
// Description:
// EFI_STATUS AmiIsaIrqMask(IN OUT UINT16 *IsaIrqMask, IN BOOLEAN Get) sets
// or retrieves the ISA IRQ mask from NVRAM depending upon the Get input.
//
// Input:
// IN OUT UINT16 *IsaIrqMask
// If Get is TRUE, returns an address to the ISA IRQ mask. If Get is FALSE,
// used to update the ISA IRQ mask NVRAM variable. User is responsible for
// allocating and managing this memory.
//
// IN BOOLEAN Get
// If TRUE, causes function to return an address to the ISA IRQ mask.
// If FALSE, causes function to use the user provided ISA IRQ mask to update
// the NVRAM variable with its value.
//
// Output:
// EFI_NOT_FOUND, if the ISA IRQ mask NVRAM variable is not found.
// EFI_DEVICE_ERROR, if the ISA IRQ mask NVRAM variable could not be
// accessed due to a hardware error.
// EFI_SECURITY_VIOLATION, if the ISA IRQ mask NVRAM variable could be not
// be accessed due to a authentication failure.
// Otherwise, EFI_SUCCESS.
//
// Modified:
//
// Referrals:
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
EFI_STATUS AmiIsaIrqMask(UINT16 *IsaIrqMask, BOOLEAN Get)
{
UINTN sz=sizeof(UINT16);
EFI_STATUS Status;
//-----------------------
if (Get) Status = pRS->GetVariable(L"IsaIrqMask", &gAmiIsaDmaIrqMaskVarGuid, NULL, &sz, IsaIrqMask);
else Status=pRS->SetVariable(L"IsaIrqMask",&gAmiIsaDmaIrqMaskVarGuid,EFI_VARIABLE_BOOTSERVICE_ACCESS, sz, IsaIrqMask);
return Status;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: AmiIsaDmaMask
//
// Description:
// EFI_STATUS AmiIsaDmaMask(IN OUT UINT8 *IsaDmaMask, IN BOOLEAN Get) sets
// or retrieves the ISA DMA mask from NVRAM depending upon the Get input.
//
// Input:
// IN OUT UINT8 *IsaDmaMask
// If Get is TRUE, returns an address to the ISA DMA mask. If Get is FALSE,
// used to update the ISA DMA mask NVRAM variable. User is responsible for
// allocating and managing this memory.
//
// IN BOOLEAN Get
// If TRUE, causes function to return an address to the ISA DMA mask.
// If FALSE, causes function to use the user provided ISA DMA mask to update
// the NVRAM variable with its value.
//
// Output:
// EFI_NOT_FOUND, if the ISA DMA mask NVRAM variable is not found.
// EFI_DEVICE_ERROR, if the ISA DMA mask NVRAM variable could not be
// accessed due to a hardware error.
// EFI_SECURITY_VIOLATION, if the ISA DMA mask NVRAM variable could be not
// be accessed due to a authentication failure.
// Otherwise, EFI_SUCCESS.
//
// Modified:
//
// Referrals:
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
EFI_STATUS AmiIsaDmaMask(UINT8 *IsaDmaMask, BOOLEAN Get)
{
UINTN sz=sizeof(UINT8);
EFI_STATUS Status;
//-----------------------
if (Get) Status = pRS->GetVariable(L"IsaDmaMask", &gAmiIsaDmaIrqMaskVarGuid, NULL, &sz, IsaDmaMask);
else Status=pRS->SetVariable(L"IsaDmaMask",&gAmiIsaDmaIrqMaskVarGuid,EFI_VARIABLE_BOOTSERVICE_ACCESS, sz, IsaDmaMask);
return Status;
}
static EFI_GUID gAmiPciOutOfResVarGuid = AMI_PCI_OUT_OF_RESOURCES_GUID;
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: AmiPciOutOfRes
//
// Description:
// EFI_STATUS AmiPciOutOfRes(AMI_OUT_OF_RES_VAR *AmiOutOfResData, IN BOOLEAN Get) sets
// or retrieves the AMI_OUT_OF_RES_DATA from NVRAM depending upon the Get input.
//
// Input:
// AMI_OUT_OF_RES_VAR *AmiOutOfResData
// If Get is TRUE, returns an address to the AMI_OUT_OF_RES_VAR. If Get is FALSE,
// used to update the AMI_OUT_OF_RES_VAR data NVRAM variable. User is responsible for
// allocating and managing this memory.
//
// IN BOOLEAN Get
// If TRUE, causes function to return an address to the ISA DMA mask.
// If FALSE, causes function to use the user provided ISA DMA mask to update
// the NVRAM variable with its value.
//
// Output:
// EFI_NOT_FOUND, if the NVRAM variable is not found.
// EFI_DEVICE_ERROR, if the NVRAM variable could not be
// accessed due to a hardware error.
// EFI_SECURITY_VIOLATION, if the NVRAM variable could be not
// be accessed due to a authentication failure.
// Otherwise, EFI_SUCCESS.
//
// Modified:
//
// Referrals:
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
EFI_STATUS AmiPciOutOfRes(AMI_OUT_OF_RES_VAR *AmiOutOfResData, BOOLEAN Get)
{
AMI_OUT_OF_RES_VAR orv;
UINTN sz=sizeof(AMI_OUT_OF_RES_VAR);
EFI_STATUS Status;
//-----------------------
if(!Get && AmiOutOfResData==NULL) return EFI_INVALID_PARAMETER;
if (Get) Status = pRS->GetVariable(L"AmiOutOfRes", &gAmiPciOutOfResVarGuid, NULL, &sz, &orv);
else Status=pRS->SetVariable(L"AmiOutOfRes",&gAmiPciOutOfResVarGuid,EFI_VARIABLE_BOOTSERVICE_ACCESS, sz, AmiOutOfResData);
if(Get && AmiOutOfResData!=NULL) *AmiOutOfResData=orv;
return Status;
}
//*************************************************************************
//<AMI_PHDR_START>
//
// Name: LibGetDsdt
//
// Description:
// EFI_STATUS LibGetDsdt(OUT EFI_PHYSICAL_ADDRESS *DsdtAddr,
// IN EFI_ACPI_TABLE_VERSION Version) retrieves a pointer to the DSDT ACPI
// table for the user requested Version of ACPI.
//
// Input:
// OUT EFI_PHYSICAL_ADDRESS *DsdtAddr
// Address of the DSDT associated with the user provided Version.
//
// IN EFI_ACPI_TABLE_VERSION Version
// Which version of ACPI's DSDT to return. Valid values include:
// EFI_ACPI_TABLE_VERSION_1_0B, EFI_ACPI_TABLE_VERSION_X,
// EFI_ACPI_TABLE_VERSION_NONE
//
// Output:
// EFI_NOT_AVAILABLE_YET, if ACPI support protocol not installed yet.
// Otherwise, EFI_SUCCESS.
//
// Modified:
//
// Referrals:
//
// Notes:
//
//<AMI_PHDR_END>
//*************************************************************************
EFI_STATUS LibGetDsdt(EFI_PHYSICAL_ADDRESS *DsdtAddr, EFI_ACPI_TABLE_VERSION Version)
{
static EFI_PHYSICAL_ADDRESS Dsdt1 = 0;
static EFI_PHYSICAL_ADDRESS Dsdt2 = 0;
#if PI_SPECIFICATION_VERSION < 0x10014
ACPI_HDR *tbl = NULL;
EFI_ACPI_SUPPORT_PROTOCOL *as;
#else
EFI_ACPI_SDT_HEADER *tbl = NULL;
EFI_ACPI_SDT_PROTOCOL *as;
#endif
EFI_STATUS Status = EFI_NOT_FOUND;
UINTN i;
EFI_ACPI_TABLE_VERSION ver;
UINTN AcpiHandle;
//---------------------------
if (!(Dsdt1 && Dsdt2)) {
#if PI_SPECIFICATION_VERSION < 0x10014
Status=pBS->LocateProtocol(&gEfiAcpiSupportGuid, NULL, &as);
#else
Status=pBS->LocateProtocol(&gLocalEfiAcpiSdtProtocolGuid, NULL, &as);
#endif
if (EFI_ERROR(Status)) {
TRACE((-1,"AcpiResLib: LibGetDsdt(): LocateProtocol(ACPISupport) returned %r \n", Status));
return EFI_NOT_AVAILABLE_YET;
} else {
for (i=0; ; i++) {
#if PI_SPECIFICATION_VERSION < 0x10014
Status = as->GetAcpiTable(as, i, &tbl, &ver, &AcpiHandle);
#else
Status = as->GetAcpiTable(i, &tbl, &ver, &AcpiHandle);
#endif
if (EFI_ERROR(Status)) {
TRACE((-1,"Can't find FADT table -> %r search %d Tables\n", Status, i));
break;
}
if (tbl->Signature == FACP_SIG) {
if (ver == EFI_ACPI_TABLE_VERSION_1_0B) {
Dsdt1 = (EFI_PHYSICAL_ADDRESS)(((FACP_20 *)tbl)->DSDT);
TRACE((-1,"AcpiResLib: LibGetDsdt(): Found v1.0b RSDT->DSDT @ 0x%lX; -> %r \n", Dsdt1, Status));
}
if ((ver & EFI_ACPI_TABLE_VERSION_X)!= 0) {
Dsdt2 = (EFI_PHYSICAL_ADDRESS)(((FACP_20 *)tbl)->X_DSDT);
TRACE((-1,"AcpiResLib: LibGetDsdt(): Found v2.0&UP XSDT->DSDT @ 0x%lX; -> %r \n", Dsdt2, Status));
}
}
pBS->FreePool((VOID *)tbl);
if (Dsdt1 && Dsdt2)
break;
}
}
}
if (Dsdt2 && ((Version & EFI_ACPI_TABLE_VERSION_X) || (Version & EFI_ACPI_TABLE_VERSION_NONE))) {
*DsdtAddr = Dsdt2;
Status = EFI_SUCCESS;
} else {
if (Dsdt1 && ((Version & EFI_ACPI_TABLE_VERSION_1_0B) || (Version & EFI_ACPI_TABLE_VERSION_NONE))) {
*DsdtAddr = Dsdt1;
Status = EFI_SUCCESS;
}
}
return Status;
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
//----------------------------------------------------------------------
//*************************************************************************
//*************************************************************************
//** **
//** (C)Copyright 1985-2010, American Megatrends, Inc. **
//** **
//** All Rights Reserved. **
//** **
//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
//** **
//** Phone: (770)-246-8600 **
//** **
//*************************************************************************
//*************************************************************************