From b7c51c9cf4864df6aabb99a1ae843becd577237c Mon Sep 17 00:00:00 2001 From: raywu Date: Fri, 15 Jun 2018 00:00:50 +0800 Subject: init. 1AQQW051 --- Library/AcpiRes.c | 2309 +++++++++++++++++ Library/AmiBufferValidationLib.chm | Bin 0 -> 42727 bytes Library/AmiBufferValidationLib.cif | 13 + Library/AmiBufferValidationLib.mak | 64 + Library/AmiBufferValidationLib.sdl | 16 + Library/AmiDxeLib.cif | 13 + Library/AmiDxeLib.mak | 93 + Library/AmiDxeLib.sdl | 20 + Library/AmiLib.chm | Bin 0 -> 203333 bytes Library/AmiLib.cif | 17 + Library/AmiLib.sdl | 9 + Library/AmiPeiLib.cif | 10 + Library/AmiPeiLib.mak | 96 + Library/AmiPeiLib.sdl | 28 + Library/Debug.c | 311 +++ Library/Decompress.c | 1046 ++++++++ Library/EfiDBE.c | 891 +++++++ Library/EfiLib.c | 4779 +++++++++++++++++++++++++++++++++++ Library/IO.c | 664 +++++ Library/LibSrc.cif | 14 + Library/LibSrc.sdl | 10 + Library/Library.cif | 10 + Library/Library.sdl | 36 + Library/LinkedList.c | 355 +++ Library/LzmaDecode.c | 1592 ++++++++++++ Library/Memory.c | 340 +++ Library/Misc.c | 220 ++ Library/PELoader.c | 800 ++++++ Library/PeiLib.c | 1132 +++++++++ Library/Print.c | 414 +++ Library/SmmAmiBufferValidationLib.c | 239 ++ Library/StdLibC.c | 1831 ++++++++++++++ Library/Tokens.c | 522 ++++ 33 files changed, 17894 insertions(+) create mode 100644 Library/AcpiRes.c create mode 100644 Library/AmiBufferValidationLib.chm create mode 100644 Library/AmiBufferValidationLib.cif create mode 100644 Library/AmiBufferValidationLib.mak create mode 100644 Library/AmiBufferValidationLib.sdl create mode 100644 Library/AmiDxeLib.cif create mode 100644 Library/AmiDxeLib.mak create mode 100644 Library/AmiDxeLib.sdl create mode 100644 Library/AmiLib.chm create mode 100644 Library/AmiLib.cif create mode 100644 Library/AmiLib.sdl create mode 100644 Library/AmiPeiLib.cif create mode 100644 Library/AmiPeiLib.mak create mode 100644 Library/AmiPeiLib.sdl create mode 100644 Library/Debug.c create mode 100644 Library/Decompress.c create mode 100644 Library/EfiDBE.c create mode 100644 Library/EfiLib.c create mode 100644 Library/IO.c create mode 100644 Library/LibSrc.cif create mode 100644 Library/LibSrc.sdl create mode 100644 Library/Library.cif create mode 100644 Library/Library.sdl create mode 100644 Library/LinkedList.c create mode 100644 Library/LzmaDecode.c create mode 100644 Library/Memory.c create mode 100644 Library/Misc.c create mode 100644 Library/PELoader.c create mode 100644 Library/PeiLib.c create mode 100644 Library/Print.c create mode 100644 Library/SmmAmiBufferValidationLib.c create mode 100644 Library/StdLibC.c create mode 100644 Library/Tokens.c (limited to 'Library') diff --git a/Library/AcpiRes.c b/Library/AcpiRes.c new file mode 100644 index 0000000..dbceb74 --- /dev/null +++ b/Library/AcpiRes.c @@ -0,0 +1,2309 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (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 32 12/22/11 12:26p Felixp $ +// +// $Revision: 32 $ +// +// $Date: 12/22/11 12:26p $ +//************************************************************************* +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/Library/AcpiRes.c $ +// +// 32 12/22/11 12:26p Felixp +// Bug fix in GetRbAmlPackagePointer. +// Wrong pointer math in the first paramater of the first GetAslObj call. +// +// 31 11/15/11 11:59a Felixp +// [TAG] EIP73021 +// [Category] Improvement +// [Description] LibGetDsdt: initialize Status variable with default +// value (EFI_NOT_FOUND) +// +// 30 11/11/11 3:14p Artems +// PI 1.2 support: Use ACPI_SDT protocol in PI 1.2 mode +// +// 29 4/08/11 2:26p Yakovlevs +// [TAG] EIP55537 +// [Category] New Feature +// [Description] Request for ACPI library function to dynamically modify +// Package objects +// [Files] AcpiRes.c; AcpiRes.h +// +// 28 4/05/11 2:01p Yakovlevs +// [TAG] EIP38174 +// [Category] New Feature +// [Description] Generic support to handle PCI OUT OF RESOURDCES added. +// AmiPciOutOfRes() function added. +// [Files] AcpiRes.h +// +// 27 4/28/10 2:31p Oleksiyy +// EIP 35563 LibGetDsdt fixed for only ACPI 1.1 tables case. +// +// 26 2/23/10 11:23p Felixp +// +// 25 2/19/10 11:37a Oleksiyy +// EIP 35099: HideAslMethodFromOs function added, which replace +// leading '_' in method name with 'X'. +// +// 24 8/21/09 3:47p Yakovlevs +// A new function - UpdateAslNameOfDevice() was added. +// Some ASL update functions was changed to support newly added one. +// +// 23 7/10/09 4:01p Felixp +// Function headers added +// +// 22 10/21/08 3:27p Felixp +// LibGetDsdt updated to be backward compatible +// +// 21 10/14/08 4:36p Yakovlevs +// Support for EFI_ACPI_TABLE_VERSION_3_0 added in LibGetDsdt() function. +// +// 20 10/01/08 12:57p Yakovlevs +// ValidateDescriptorBlock() function implementation changed to accomodate +// recent PciBus Driver changes +// +// 19 3/30/07 3:44p Felixp +// Comments added +// +// 18 3/29/07 11:01a Yakovlevs +// Added LibGetDsdt() function implementation; file header fixed. +//************************************************************************* +// +// +// Name: AcpiRes.c +// +// Description: +// Implementation of ASL MACROs for ResourceTemplate. See ACPI 2.0 +// specification section 16.2.4. +// +// +//************************************************************************* +#include +#include +#include + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +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_INT=irq; + return rb; +} + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +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_INT=irq; + return rb; +} + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +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_DMA=dma; + + return rb; +} + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +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; iDepRes.Items[i]=va_arg(marker, VOID*); + + return rb; +} + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +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; iDepRes.Items[i]=va_arg(marker, VOID*); + + return rb; +} + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +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; +} + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +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; +} + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +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 +// +// 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: +// +// +//************************************************************************* +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 + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +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; +} + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +EFI_STATUS InsertItemLst(T_ITEM_LIST *Lst, VOID* pRes, UINTN ItemIndex) +{ + INTN i; + +//---------------- + if (!Lst->ItemCount && Lst->ItemCountItemCount-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; +} + + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +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; iItemCount-1; i++) Lst->Items[i]=Lst->Items[i+1]; + + //Adjust Item Count + Lst->ItemCount--; + return EFI_SUCCESS; +} + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +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; +} + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +VOID ClearItemLst(T_ITEM_LIST *Lst, BOOLEAN FreeData) +{ + UINTN i; + +//----------------------------------------- + if (FreeData)for (i=0; iItemCount; 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; +} + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +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; +} + +//************************************************************************* +// +// +// 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. +// +// +//************************************************************************* +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; +} + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +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; +} + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +BOOLEAN CheckDsdt(ACPI_HDR *Dsdt) +{ + if (Dsdt->Signature!=DSDT_SIG) return FALSE; + + return TRUE; +} + + +// +//---------------------------------------------------------------------------- +// +// 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); +// ... +// } +// +// +//-------------------------------------------------------------------------- +// + +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; +} + + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +//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; +} + +//************************************************************************* +// +// +// 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. +// +// +//************************************************************************* +UINT32 ConvertAslName(UINT8 *AslName) +{ + AML_NAME_SEG n; + UINTN l=Strlen(AslName); +//------------------------- + n.NAME=0x5F5F5F5F; + MemCpy(&n.Name[0],AslName,l); + return n.NAME; +} + +//************************************************************************* +// +// +// 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. +// +// +//************************************************************************* +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; iNAME!=nm.NAME)continue; + + return &p[i]; + } + + return NULL; +} +//************************************************************************* +// +// +// 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 +// +// +//************************************************************************* +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; + } + } + +} + + +//************************************************************************* +// +// +// 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. +// +// +//************************************************************************* +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; +} + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +//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; +} + + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +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; +} + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +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; +} + + + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +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); +} + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +UINT8 ChsumTbl(UINT8* TblStart, UINT32 BytesCount) +{ + UINTN i; + UINT8 res=*TblStart; + + for (i=1; i +// +// 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: +// +// +//************************************************************************* +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; +} + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +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; + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +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; +} + +//************************************************************************* +// +// +// 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: +// +// +//************************************************************************* +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(&gEfiAcpiSdtProtocolGuid, 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 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Library/AmiBufferValidationLib.chm b/Library/AmiBufferValidationLib.chm new file mode 100644 index 0000000..958ad0a Binary files /dev/null and b/Library/AmiBufferValidationLib.chm differ diff --git a/Library/AmiBufferValidationLib.cif b/Library/AmiBufferValidationLib.cif new file mode 100644 index 0000000..ea7ab40 --- /dev/null +++ b/Library/AmiBufferValidationLib.cif @@ -0,0 +1,13 @@ + + name = "AmiBufferValidationLib" + category = eModule + LocalRoot = "Library" + RefName = "AmiBufferValidationLib" +[files] +"AmiBufferValidationLib.sdl" +"AmiBufferValidationLib.mak" +"AmiBufferValidationLib.chm" +"SmmAmiBufferValidationLib.c" +[parts] +"AmiBufferValidationLibInclude" + diff --git a/Library/AmiBufferValidationLib.mak b/Library/AmiBufferValidationLib.mak new file mode 100644 index 0000000..c2b704c --- /dev/null +++ b/Library/AmiBufferValidationLib.mak @@ -0,0 +1,64 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2014, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** + +#********************************************************************** +# $Header: /Alaska/SOURCE/Modules/AmiBufferValidationLib/AmiBufferValidationLib.mak 1 11/07/14 12:07p Aaronp $ +# +# $Revision: 1 $ +# +# $Date: 11/07/14 12:07p $ +#********************************************************************** +# Revision History +# ---------------- +# $Log: /Alaska/SOURCE/Modules/AmiBufferValidationLib/AmiBufferValidationLib.mak $ +# +# 1 11/07/14 12:07p Aaronp +# Initial addition of AmiBufferValidationLib +# +#********************************************************************** + +#********************************************************************** +# +# +# Name: AmiBufferValidationLib.mak +# +# Description: +# +# +#********************************************************************** +all : AmiBufferValidationLib + +AmiBufferValidationLib : $(BUILD_DIR)\AmiBufferValidationLib.mak AmiBufferValidationLibBin + +$(BUILD_DIR)\AmiBufferValidationLib.mak : $(LIBRARY_DIR)\$(@B).cif $(LIBRARY_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(LIBRARY_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +AmiBufferValidationLibBin : $(AMIDXELIB) + $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\ + /f $(BUILD_DIR)\AmiBufferValidationLib.mak all\ + TYPE=LIBRARY + +$(BUILD_DIR)\AmiBufferValidationLib.lib : AmiBufferValidationLib +#********************************************************************** +#** ** +#** (C)Copyright 1985-2014, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** \ No newline at end of file diff --git a/Library/AmiBufferValidationLib.sdl b/Library/AmiBufferValidationLib.sdl new file mode 100644 index 0000000..8601607 --- /dev/null +++ b/Library/AmiBufferValidationLib.sdl @@ -0,0 +1,16 @@ +TOKEN + Name = "AmiBufferValidationLib_SUPPORT" + Value = "1" + Help = "Main switch to enable AmiBufferValidationLib support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + TargetH = Yes + Master = Yes +End + +MODULE + Help = "Includes AmiBufferValidationLib.mak to Project" + File = "AmiBufferValidationLib.mak" +End + diff --git a/Library/AmiDxeLib.cif b/Library/AmiDxeLib.cif new file mode 100644 index 0000000..edc10cd --- /dev/null +++ b/Library/AmiDxeLib.cif @@ -0,0 +1,13 @@ + + name = "AmiDxeLib" + category = ModulePart + LocalRoot = "Library\" + RefName = "AmiDxeLib" +[files] +"\AmiDxeLib.sdl" +"\AmiDxeLib.mak" +"\EfiDBE.c" +"\EfiLib.c" +"\AcpiRes.c" +"\Print.c" + diff --git a/Library/AmiDxeLib.mak b/Library/AmiDxeLib.mak new file mode 100644 index 0000000..d908003 --- /dev/null +++ b/Library/AmiDxeLib.mak @@ -0,0 +1,93 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2005, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** + +#********************************************************************** +# $Header: /Alaska/SOURCE/Core/Library/AmiDxeLib.mak 7 8/24/06 9:27a Felixp $ +# +# $Revision: 7 $ +# +# $Date: 8/24/06 9:27a $ +#********************************************************************** +# Revision History +# ---------------- +# $Log: /Alaska/SOURCE/Core/Library/AmiDxeLib.mak $ +# +# 7 8/24/06 9:27a Felixp +# Preliminary x64 support (work in progress) +# +# 6 3/17/06 4:24p Felixp +# +# 5 12/02/05 11:19a Felixp +# +# 4 7/28/05 3:56p Yul +# dependecy deom token.h added +# +# 3 1/28/05 1:09p Felixp +# +# 2 1/18/05 3:22p Felixp +# PrintDebugMessage renamed to Trace +# +# 1 12/23/04 9:42a Felixp +# +# 5 12/15/04 9:06p Felixp +# LegacyBoot application added +# Minor build process improvements +# +# 4 11/05/04 7:55p Felixp +# +# 3 11/01/04 7:59a Felixp +# +# 2 10/05/04 5:36p Felixp +# +# 1 10/04/04 4:34p Felixp +# +#********************************************************************** +# +# +# Name: AmiDxeLib.mak +# +# Description: +# +# +#********************************************************************** +all : AmiDxeLib + +AmiDxeLib_DIR=$(LIBRARY_DIR) + +AmiDxeLib : $(BUILD_DIR)\AmiDxeLib.mak AmiDxeLibBin + +$(BUILD_DIR)\AmiDxeLib.mak : $(AmiDxeLib_DIR)\$(@B).cif $(AmiDxeLib_DIR)\$(@B).mak $(BUILD_RULES) $(LIBRARY_DIR)\AmiLib.cif + $(CIF2MAK) $(AmiDxeLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) $(LIBRARY_DIR)\AmiLib.cif + +AmiDxeLibBin : + $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\ + /f $(BUILD_DIR)\AmiDxeLib.mak all\ +!IF $(DEBUG_MODE)!=0 + EXT_HEADERS=$(BUILD_DIR)\token.h\ +!ENDIF + TYPE=LIBRARY + +$(BUILD_DIR)\AmiDxeLib.lib : AmiDxeLib +#********************************************************************** +#** ** +#** (C)Copyright 1985-2005, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** \ No newline at end of file diff --git a/Library/AmiDxeLib.sdl b/Library/AmiDxeLib.sdl new file mode 100644 index 0000000..49ca586 --- /dev/null +++ b/Library/AmiDxeLib.sdl @@ -0,0 +1,20 @@ +TOKEN + Name = "AmiDxeLib_SUPPORT" + Value = "1" + Help = "Main switch to enable AmiDxeLib support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +MODULE + Help = "Includes AmiDxeLib.mak to Project" + File = "AmiDxeLib.mak" +End + +ELINK + Name = "$(BUILD_DIR)\AmiDxeLib.lib" + Parent = "$(LIBRARY_DIR)\AmiDxeLib$(ARCH)$(DBG).lib" + InvokeOrder = ReplaceParent +End \ No newline at end of file diff --git a/Library/AmiLib.chm b/Library/AmiLib.chm new file mode 100644 index 0000000..2c6e4d2 Binary files /dev/null and b/Library/AmiLib.chm differ diff --git a/Library/AmiLib.cif b/Library/AmiLib.cif new file mode 100644 index 0000000..e510e68 --- /dev/null +++ b/Library/AmiLib.cif @@ -0,0 +1,17 @@ + + name = "AmiLib" + category = ModulePart + LocalRoot = "Library\" + RefName = "AmiLib" +[files] +"AmiLib.sdl" +"PELoader.c" +"Decompress.c" +"Memory.c" +"Debug.c" +"StdLibC.c" +"Misc.c" +"IO.c" +"LzmaDecode.c" +"LinkedList.c" + diff --git a/Library/AmiLib.sdl b/Library/AmiLib.sdl new file mode 100644 index 0000000..78e70fa --- /dev/null +++ b/Library/AmiLib.sdl @@ -0,0 +1,9 @@ +TOKEN + Name = "AmiLib_SUPPORT" + Value = "1" + Help = "Main switch to enable AmiLib support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End diff --git a/Library/AmiPeiLib.cif b/Library/AmiPeiLib.cif new file mode 100644 index 0000000..df85ed5 --- /dev/null +++ b/Library/AmiPeiLib.cif @@ -0,0 +1,10 @@ + + name = "AmiPeiLib" + category = ModulePart + LocalRoot = "Library\" + RefName = "AmiPeiLib" +[files] +"\AmiPeiLib.sdl" +"\AmiPeiLib.mak" +"\PeiLib.c" + diff --git a/Library/AmiPeiLib.mak b/Library/AmiPeiLib.mak new file mode 100644 index 0000000..f059a80 --- /dev/null +++ b/Library/AmiPeiLib.mak @@ -0,0 +1,96 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2006, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** + +#********************************************************************** +# $Header: /Alaska/SOURCE/Core/Library/AmiPeiLib.mak 7 8/25/06 10:55a Felixp $ +# +# $Revision: 7 $ +# +# $Date: 8/25/06 10:55a $ +#********************************************************************** +# Revision History +# ---------------- +# $Log: /Alaska/SOURCE/Core/Library/AmiPeiLib.mak $ +# +# 7 8/25/06 10:55a Felixp +# +# 6 8/24/06 9:27a Felixp +# Preliminary x64 support (work in progress) +# +# 5 3/17/06 4:24p Felixp +# +# 4 12/02/05 11:19a Felixp +# +# 3 1/28/05 1:09p Felixp +# +# 2 1/18/05 3:22p Felixp +# PrintDebugMessage renamed to Trace +# +# 1 12/23/04 9:42a Felixp +# +# 6 12/15/04 9:06p Felixp +# LegacyBoot application added +# Minor build process improvements +# +# 5 11/05/04 7:55p Felixp +# +# 4 11/01/04 7:59a Felixp +# +# 3 10/05/04 5:39p Felixp +# +# 1 10/04/04 4:34p Felixp +# +#********************************************************************** +# +# +# Name: AmiPeiLib.mak +# +# Description: +# +# +#********************************************************************** +all : AmiPeiLib + +AmiPeiLib_DIR=$(LIBRARY_DIR) + +AmiPeiLib : $(BUILD_DIR)\AmiPeiLib.mak AmiPeiLibBin + +$(BUILD_DIR)\AmiPeiLib.mak : $(AmiPeiLib_DIR)\$(@B).cif $(AmiPeiLib_DIR)\$(@B).mak $(BUILD_RULES) $(LIBRARY_DIR)\AmiLib.cif + $(CIF2MAK) $(AmiPeiLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) $(LIBRARY_DIR)\AmiLib.cif + +AmiPeiLibBin : + $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\ +!IF "$(x64_BUILD)"=="1" + BUILD_DIR=$(BUILD_DIR)\IA32\ + "CFLAGS=$(CFLAGS) /D\"PE_LOADER_SUPPORT_ALL=1\""\ +!ELSE + BUILD_DIR=$(BUILD_DIR)\ +!ENDIF + /f $(BUILD_DIR)\AmiPeiLib.mak all\ + TYPE=PEI_LIBRARY LIBRARY_NAME=$(BUILD_DIR)\AmiPeiLib.lib + +$(BUILD_DIR)\AmiPeiLib.lib : AmiPeiLib +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2006, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** \ No newline at end of file diff --git a/Library/AmiPeiLib.sdl b/Library/AmiPeiLib.sdl new file mode 100644 index 0000000..c2de593 --- /dev/null +++ b/Library/AmiPeiLib.sdl @@ -0,0 +1,28 @@ +TOKEN + Name = "AmiPeiLib_SUPPORT" + Value = "1" + Help = "Main switch to enable AmiPeiLib support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +MODULE + Help = "Includes AmiPeiLib.mak to Project" + File = "AmiPeiLib.mak" +End + +ELINK + Name = "$(BUILD_DIR)\AmiPeiLib.lib" + Parent = "$(LIBRARY_DIR)\AmiPeiLib$(ARCH)$(DBG).lib" + InvokeOrder = ReplaceParent +End + +TOKEN + Name = "MAX_PEI_PERF_LOG_ENTRIES" + Value = "28" + Help = "Maximum allowed number of PEI performance management entries in log database" + TokenType = Integer + TargetH = Yes +End \ No newline at end of file diff --git a/Library/Debug.c b/Library/Debug.c new file mode 100644 index 0000000..02cb692 --- /dev/null +++ b/Library/Debug.c @@ -0,0 +1,311 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//************************************************************************* +// $Header: /Alaska/SOURCE/Core/Library/Debug.c 10 7/30/09 4:39p Vyacheslava $ +// +// $Revision: 10 $ +// +// $Date: 7/30/09 4:39p $ +//************************************************************************* +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/Library/Debug.c $ +// +// 10 7/30/09 4:39p Vyacheslava +// Minor bug fix. EIP#24453: Synopsis: CPU exception when printing long +// debug messages. +// +// 9 7/28/09 4:54p Vyacheslava +// Bug fix. EIP#24453: Synopsis: CPU exception when printing long +// debug messages. +// +// 8 7/10/09 3:49p Felixp +// Function headers added +// +// 7 8/24/06 9:26a Felixp +// Preliminary x64 support (work in progress): +// 1. Processor architecture specific functions moved to a processor +// library +// 2. Makefile removed (AmiLib files are build by the AmiPeiLib and +// AmeDxeLib makefile) +// 3. Tokens.c added +// +// 6 3/13/06 1:49a Felixp +// +// 5 3/04/05 10:50a Mandal +// +// 4 1/19/05 5:03p Felixp +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 12/23/04 9:41a Felixp +// +// 5 11/24/04 9:36a Felixp +// GetCpuTimer added +// +// 4 10/22/04 8:01p Felixp +// +// 3 10/22/04 7:42p Felixp +// +// 2 7/13/04 10:42a Felixp +// +// 1 7/12/04 6:31p Felixp +// +//************************************************************************* +// +// +// Name: Debug.c +// +// Description: +// Contains generic debug library functions. +// +// +//************************************************************************* +#include +#include + +//************************************************************************* +// +// +// Name: Debug_Functions +// +// Description: +// Debug related functions defined in the AMI library. +// +// Fields: Header Function Description +// ------------------------------------------------------------------ +// AmiPeiLib PEI_TRACE Macro which creates a serial debug message in PEI. +// AmiDxeLib TRACE Macro which creates a serial debug message in DXE. +// AmiDxeLib PROGRESS_CODE Macro to report boot progress information in DXE. +// AmiPeiLib PEI_PROGRESS_CODE Macro report boot progress information in PEI. +// AmiDxeLib ERROR_CODE Macro to report error condition in DXE. +// AmiPeiLib PEI_ERROR_CODE Macro to report error condition in PEI. +// AmiLib checkpoint Send a checkpoint to port 0x80. Use PROGRESS_CODE or PEI_PROGRESS_CODE if possible. +// +// Notes: +// Header details which header file contains the function prototype for +// the above functions. Append .h to the given name. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: PROGRESS_CODE +// +// Description: +// PROGRESS_CODE(Code) is a macro which reports progress code +// using UEFI ReportStatusCode API. +// +// Input: +// Code - progress code value. +// Standard values are defined in AmiStatusCodes.h +// +// Output: +// VOID. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: PEI_PROGRESS_CODE +// +// Description: +// PEI_PROGRESS_CODE(PeiServices, Code) is a macro which reports progress code +// using (*PeiServices)->ReportStatusCode +// +// Input: +// PeiServices - Double pointer to PEI Services Table. +// Code - progress code value. +// Standard values are defined in AmiStatusCodes.h +// +// Output: +// VOID. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: PEI_TRACE +// +// Description: +// PEI_TRACE(Arguments) is a macro which creates a serial debug message in +// PEI if the DEBUG_MODE SDL token is enabled by invoking the PeiTrace +// function with the provided arguments. If DEBUG_MODE is off, nothing is +// generated. See notes for an example usage. +// +// Input: +// Arguments +// A bracket enclosed list including the following input parameters for +// PeiTrace (in order from left to right). +// +// IN UINTN Level +// The error level of the debug message. +// +// IN EFI_PEI_SERVICES **ppPS +// Double pointer to PEI Services Table. +// +// IN CHAR8 *sFormat +// Format string for the debug message to print. +// +// IN ... +// Additional parameters utilized by the format string. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// PeiTrace +// Sprintf +// +// Notes: +// See Sprintf for a detailed description of the format string parameters. +// Example usage: +// +// PEI_TRACE((TRACE_ALWAYS, PeiServices, "This is a test message. Status +// is %r.\n", Status)); +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: TRACE +// +// Description: +// TRACE(Arguments) is a macro which creates a serial debug message in DXE +// if the DEBUG_MODE SDL token is enabled by invoking the Trace function with +// the provided arguments. If DEBUG_MODE is off, nothing is generated. See +// notes for an example usage. +// +// Input: +// Arguments +// A bracket enclosed list including the following input parameters for +// Trace (in order from left to right). +// +// IN UINTN Level +// The error level of the debug message. +// +// IN CHAR8 *sFormat +// Format string for the debug message to print. +// +// IN ... +// Argument list for the format string. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// Trace +// Sprintf +// +// Notes: +// See Sprintf for a detailed description of the format string parameters. +// Example usage: +// +// TRACE((TRACE_ALWAYS, "This is a test message. Status is %r.\n", Status)); +// +// +//************************************************************************* + +//************************************************************************* +// +// Name: PrepareStatusCodeString +// +// Description: Produces a Status Code ASCII string in the output +// buffer. The ASCII string is produced by parsing the format string +// specified by format. Arguments are pulled from the variable argument +// list specified by ArgList based on the contents of the format string. +// This is internal function used by TRACE and PEI_TRACE +// +// Input: +// pBuffer - Pointer to a EFI_STATUS_CODE_STRING_DATA buffer. User is +// responsible for allocating the necessary memory resources! +// +// Size - Size of the buffer in bytes. +// +// sFormat - Pointer to a null-terminated format ASCII string. +// +// ArgList - Marker for the variable argument list. +// +// Output: VOID +// +// Referrals: Sprintf_va_list +// +// +//************************************************************************* +VOID PrepareStatusCodeString( VOID* pBuffer, UINTN Size, CHAR8 *sFormat, va_list ArgList ) +{ + static CHAR8 OverflowMessageStr[] = "... DEBUG BUFFER OVERFLOW!!!\n"; + UINTN n; + + static EFI_STATUS_CODE_STRING_DATA Header = + { + { + sizeof(EFI_STATUS_CODE_DATA), + sizeof(EFI_STATUS_CODE_STRING_DATA) - sizeof(EFI_STATUS_CODE_DATA), + EFI_STATUS_CODE_DATA_TYPE_STRING_GUID + }, EfiStringAscii, NULL + }; + EFI_STATUS_CODE_STRING_DATA *pData = pBuffer; + + //Prepare the data strucutre + *pData = Header; + pData->String.Ascii = (CHAR8*)pData + sizeof(EFI_STATUS_CODE_STRING_DATA); + + //Prepare the string + n = Sprintf_s_va_list( + (CHAR8*)(pData + 1), + Size - sizeof(EFI_STATUS_CODE_STRING_DATA), + sFormat, + ArgList + ); + if ( n < (Size - sizeof(EFI_STATUS_CODE_STRING_DATA) - 1) || + Size < (sizeof(OverflowMessageStr) + sizeof(EFI_STATUS_CODE_STRING_DATA)) ) + return; + + // Buffer Overflow! + // Cut of the previous debug message plus error message + MemCpy( + (CHAR8*)pBuffer + Size - sizeof(OverflowMessageStr), + OverflowMessageStr, + sizeof(OverflowMessageStr) + ); +} + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Library/Decompress.c b/Library/Decompress.c new file mode 100644 index 0000000..6292ecf --- /dev/null +++ b/Library/Decompress.c @@ -0,0 +1,1046 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//************************************************************************* +// $Header: /Alaska/SOURCE/Core/Library/Decompress.c 4 7/10/09 3:49p Felixp $ +// +// $Revision: 4 $ +// +// $Date: 7/10/09 3:49p $ +//************************************************************************* +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/Library/Decompress.c $ +// +// 4 7/10/09 3:49p Felixp +// Function headers added +// +// 3 5/09/07 9:03a Felixp +// +// +//************************************************************************* +// +// +// Name: Decompress.c +// +// Description: +// Standard EFI decompressor library functions. +// The functions are used by Core to implement standard Decompression API. +// Consumers outside Core should not use functions from this file. +// The public API should be used instead. +// +// +//************************************************************************* +#include + +#define STATIC static + +// +// Decompression algorithm begins here +// + +#define BITBUFSIZ 32 +#define MAXMATCH 256 +#define THRESHOLD 3 +#define CODE_BIT 16 +#define UINT8_MAX 0xff +#define BAD_TABLE -1 + +// +// C: Char&Len Set; P: Position Set; T: exTra Set +// + +#define NC (0xff + MAXMATCH + 2 - THRESHOLD) +#define CBIT 9 +#define MAXPBIT 5 +#define TBIT 5 +#define MAXNP ((1U << MAXPBIT) - 1) +#define NT (CODE_BIT + 3) +#if NT > MAXNP + #define NPT NT +#else + #define NPT MAXNP +#endif + + +//************************************************************************* +// +// +// Name: SCRATCH_DATA +// +// Description: +// Scratch buffer structure for the (de)compression routines. +// +// Fields: +// Name Type Description +//......................................................................... +// mSrcBase UINT8* Starting address of compressed data. +// mDstBase UINT8* Starting address of decompressed data. +// mOutBuf UINT32 +// mInBuf UINT32 +// mBitCount UINT16 +// mBitBuf UINT32 +// mSubBitBuf UINT32 +// mBlockSize UINT16 +// mCompSize UINT32 +// mOrigSize UINT32 +// mBadTableFlag UINT16 +// mLeft UINT16 +// mmRight UINT16 +// mCLen UINT8 +// mPTLen UINT8 +// mCTable UINT16 +// mPTTable UINT16 +// mPBit UINT8 The length of the field 'Position Set Code Length Array Size' in Block Header. For EFI 1.1 (de)compression algorithm, mPBit = 4. For Tiano (de)compression algorithm, mPBit = 5. +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +typedef struct { + UINT8 *mSrcBase; //Starting address of compressed data + UINT8 *mDstBase; //Starting address of decompressed data + UINT32 mOutBuf; + UINT32 mInBuf; + + UINT16 mBitCount; + UINT32 mBitBuf; + UINT32 mSubBitBuf; + UINT16 mBlockSize; + UINT32 mCompSize; + UINT32 mOrigSize; + + UINT16 mBadTableFlag; + + UINT16 mLeft[2 * NC - 1]; + UINT16 mRight[2 * NC - 1]; + UINT8 mCLen[NC]; + UINT8 mPTLen[NPT]; + UINT16 mCTable[4096]; + UINT16 mPTTable[256]; + +// +// The length of the field 'Position Set Code Length Array Size' in Block Header. +// For EFI 1.1 de/compression algorithm, mPBit = 4 +// For Tiano de/compression algorithm, mPBit = 5 +// + + UINT8 mPBit; +} SCRATCH_DATA; + +//************************************************************************* +// +// +// Name: FillBuf +// +// Description: +// VOID FillBuf(IN OUT SCRATCH_DATA *Sd, IN UINT16 NumOfBits) shifts +// Sd->mBitBuf NumOfBits left. Then it reads in NumOfBits bits from source. +// +// Input: +// IN OUT SCRATCH_DATA *Sd +// The global scratch data. +// +// IN UINT16 NumOfBits +// The number of bits to shift and read. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +STATIC +VOID +FillBuf ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ) +{ + Sd->mBitBuf = (UINT32)(Sd->mBitBuf << NumOfBits); + + while (NumOfBits > Sd->mBitCount) { + + Sd->mBitBuf |= (UINT32)(Sd->mSubBitBuf << + (NumOfBits = (UINT16)(NumOfBits - Sd->mBitCount))); + + if (Sd->mCompSize > 0) { + + // + // Get 1 byte into SubBitBuf + // + Sd->mCompSize --; + Sd->mSubBitBuf = 0; + Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf ++]; + Sd->mBitCount = 8; + + } else { + + // + // No more bits from the source, just pad zero bit. + // + Sd->mSubBitBuf = 0; + Sd->mBitCount = 8; + + } + } + + Sd->mBitCount = (UINT16)(Sd->mBitCount - NumOfBits); + Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount; +} + +//************************************************************************* +// +// +// Name: GetBits +// +// Description: +// UINT32 GetBits(IN OUT SCRATCH_DATA *Sd, IN UINT16 NumOfBits) fetches +// NumOfBits bits out from mBitBuf, then fills mBitBuf with subsequent +// NumOfBits bits from source. Returns NumOfBits bits that are popped out. +// +// Input: +// IN OUT SCRATCH_DATA *Sd +// The global scratch data. +// +// IN UINT16 NumOfBits +// The number of bits to pop and read. +// +// Output: +// UINT32 number of bits that are popped out. +// +// Modified: +// +// Referrals: +// FillBuf +// +// Notes: +// +// +//************************************************************************* +STATIC +UINT32 +GetBits( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ) +{ + UINT32 OutBits; + + OutBits = (UINT32)(Sd->mBitBuf >> (BITBUFSIZ - NumOfBits)); + + FillBuf (Sd, NumOfBits); + + return OutBits; +} + +//************************************************************************* +// +// +// Nane: MakeTable +// +// Description: +// UINT16 MakeTable(IN OUT SCRATCH_DATA *Sd, IN UINT16 NumOfChar, +// IN UINT8 *BitLen, IN UINT16 TableBits, OUT UINT16 *Table) creates a +// Huffman Code mapping table according to code length array. +// +// Input: +// IN OUT SCRATCH_DATA *Sd +// The global scratch data. +// +// IN UINT16 NumOfChar +// Number of symbols in the symbol set. +// +// IN UINT8 *BitLen +// Code length array. +// +// IN UINT16 TableBits +// The width of the mapping table. +// +// OUT UINT16 *Table +// The table. +// +// Output: +// UINT16 BAD_TABLE if table is corrupted, otherwise returns 0 if okay. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +STATIC +UINT16 +MakeTable ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfChar, + IN UINT8 *BitLen, + IN UINT16 TableBits, + OUT UINT16 *Table + ) +{ + UINT16 Count[17]; + UINT16 Weight[17]; + UINT16 Start[18]; + UINT16 *p; + UINT16 k; + UINT16 i; + UINT16 Len; + UINT16 Char; + UINT16 JuBits; + UINT16 Avail; + UINT16 NextCode; + UINT16 Mask; + + + for (i = 1; i <= 16; i ++) { + Count[i] = 0; + } + + for (i = 0; i < NumOfChar; i++) { + Count[BitLen[i]]++; + } + + Start[1] = 0; + + for (i = 1; i <= 16; i ++) { + Start[i + 1] = (UINT16)(Start[i] + (Count[i] << (16 - i))); + } + + if (Start[17] != 0) {/*(1U << 16)*/ + return (UINT16)BAD_TABLE; + } + + JuBits = (UINT16)(16 - TableBits); + + for (i = 1; i <= TableBits; i ++) { + Start[i] >>= JuBits; + Weight[i] = (UINT16)(1U << (TableBits - i)); + } + + while (i <= 16) { + Weight[i++] = (UINT16)(1U << (16 - i)); + } + + i = (UINT16)(Start[TableBits + 1] >> JuBits); + + if (i != 0) { + k = (UINT16)(1U << TableBits); + while (i != k) { + Table[i++] = 0; + } + } + + Avail = NumOfChar; + Mask = (UINT16)(1U << (15 - TableBits)); + + for (Char = 0; Char < NumOfChar; Char++) { + + Len = BitLen[Char]; + if (Len == 0) { + continue; + } + + NextCode = (UINT16)(Start[Len] + Weight[Len]); + + if (Len <= TableBits) { + + for (i = Start[Len]; i < NextCode; i ++) { + Table[i] = Char; + } + + } else { + + k = Start[Len]; + p = &Table[k >> JuBits]; + i = (UINT16)(Len - TableBits); + + while (i != 0) { + if (*p == 0) { + Sd->mRight[Avail] = Sd->mLeft[Avail] = 0; + *p = Avail ++; + } + + if (k & Mask) { + p = &Sd->mRight[*p]; + } else { + p = &Sd->mLeft[*p]; + } + + k <<= 1; + i --; + } + + *p = Char; + + } + + Start[Len] = NextCode; + } + + // + // Succeeds + // + return 0; +} + +//************************************************************************* +// +// +// Name: DecodeP +// +// Description: +// UINT32 DecodeP(IN SCRATCH_DATA *Sd) decodes a position value. +// +// Input: +// IN SCRATCH_DATA *Sd +// The global scratch data. +// +// Output: +// UINT32 position value decoded. +// +// Modified: +// +// Referrals: +// FillBuf +// GetBits +// +// Notes: +// +// +//************************************************************************* +STATIC +UINT32 +DecodeP ( + IN SCRATCH_DATA *Sd + ) +{ + UINT16 Val; + UINT32 Mask; + UINT32 Pos; + + Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + + if (Val >= MAXNP) { + Mask = 1U << (BITBUFSIZ - 1 - 8); + + do { + + if (Sd->mBitBuf & Mask) { + Val = Sd->mRight[Val]; + } else { + Val = Sd->mLeft[Val]; + } + + Mask >>= 1; + } while (Val >= MAXNP); + } + + // + // Advance what we have read + // + FillBuf (Sd, Sd->mPTLen[Val]); + + Pos = Val; + if (Val > 1) { + Pos = (UINT32)((1U << (Val - 1)) + GetBits (Sd, (UINT16)(Val - 1))); + } + return Pos; +} + +//************************************************************************* +// +// +// Name: ReadPTLen +// +// Description: +// UINT16 ReadPTLen(IN OUT SCRATCH_DATA *Sd, IN UINT16 nn, IN UINT16 nbit, +// IN UINT16 Special) reads code lengths for the extra set or the position +// set. +// +// Input: +// IN OUT SCRATCH_DATA *Sd +// The global scratch data. +// +// IN UINT16 nn +// Number of symbols. +// +// IN UINT16 nbit +// Number of bits needed to represent nn. +// +// IN UINT16 Special +// The special symbol that needs to be taken care of. +// +// Output: +// UINT16 BAD_TABLE if the table is corrupted, otherwise returns 0 if +// everything okay. +// +// Modified: +// +// Referrals: +// GetBits +// FillBuf +// MakeTable +// +// Notes: +// +// +//************************************************************************* +STATIC +UINT16 +ReadPTLen ( + IN SCRATCH_DATA *Sd, + IN UINT16 nn, + IN UINT16 nbit, + IN UINT16 Special + ) +{ + UINT16 n; + UINT16 c; + UINT16 i; + UINT32 Mask; + + n = (UINT16)GetBits (Sd, nbit); + + if (n == 0) { + c = (UINT16)GetBits (Sd, nbit); + + for ( i = 0; i < 256; i ++) { + Sd->mPTTable[i] = c; + } + + for ( i = 0; i < nn; i++) { + Sd->mPTLen[i] = 0; + } + + return 0; + } + + i = 0; + + while (i < n) { + + c = (UINT16)(Sd->mBitBuf >> (BITBUFSIZ - 3)); + + if (c == 7) { + Mask = 1U << (BITBUFSIZ - 1 - 3); + while (Mask & Sd->mBitBuf) { + Mask >>= 1; + c += 1; + } + } + + FillBuf (Sd, (UINT16)((c < 7) ? 3 : c - 3)); + + Sd->mPTLen [i++] = (UINT8)c; + + if (i == Special) { + c = (UINT16)GetBits (Sd, 2); + while ((INT16)(--c) >= 0) { + Sd->mPTLen[i++] = 0; + } + } + } + + while (i < nn) { + Sd->mPTLen [i++] = 0; + } + + return ( MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable) ); +} + +//************************************************************************* +// +// +// Name: ReadCLen +// +// Description: +// VOID ReadCLen(IN OUT SCRATCH_DATA *Sd) reads code lengths for Char&Len +// Set. +// +// Input: +// IN OUT SCRATCH_DATA *Sd +// The global scratch data. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// GetBits +// MakeTable +// +// Notes: +// +// +//************************************************************************* +STATIC +VOID +ReadCLen ( + SCRATCH_DATA *Sd + ) +{ + UINT16 n; + UINT16 c; + UINT16 i; + UINT32 Mask; + + n = (UINT16)GetBits(Sd, CBIT); + + if (n == 0) { + c = (UINT16)GetBits(Sd, CBIT); + + for (i = 0; i < NC; i ++) { + Sd->mCLen[i] = 0; + } + + for (i = 0; i < 4096; i ++) { + Sd->mCTable[i] = c; + } + + return; + } + + i = 0; + while (i < n) { + + c = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + if (c >= NT) { + Mask = 1U << (BITBUFSIZ - 1 - 8); + + do { + + if (Mask & Sd->mBitBuf) { + c = Sd->mRight [c]; + } else { + c = Sd->mLeft [c]; + } + + Mask >>= 1; + + }while (c >= NT); + } + + // + // Advance what we have read + // + FillBuf (Sd, Sd->mPTLen[c]); + + if (c <= 2) { + + if (c == 0) { + c = 1; + } else if (c == 1) { + c = (UINT16)(GetBits (Sd, 4) + 3); + } else if (c == 2) { + c = (UINT16)(GetBits (Sd, CBIT) + 20); + } + + while ((INT16)(--c) >= 0) { + Sd->mCLen[i++] = 0; + } + + } else { + + Sd->mCLen[i++] = (UINT8)(c - 2); + + } + } + + while (i < NC) { + Sd->mCLen[i++] = 0; + } + + MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable); + + return; +} + +//************************************************************************* +// +// +// Name: DecodeC +// +// Description: +// UINT16 DecodeC(IN OUT SCRATCH_DATA *Sd) decodes a character/length value. +// +// Input: +// IN OUT SCRATCH_DATA *Sd +// The global scratch data. +// +// Output: +// UINT16 decoded value. +// +// Modified: +// +// Referrals: +// ReadPTLen +// ReadCLen +// GetBits +// FillBuf +// +// Notes: +// +// +//************************************************************************* +STATIC +UINT16 +DecodeC ( + SCRATCH_DATA *Sd + ) +{ + UINT16 j; + UINT32 Mask; + + if (Sd->mBlockSize == 0) { + + // + // Starting a new block + // + + Sd->mBlockSize = (UINT16)GetBits(Sd, 16); + Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3); + if (Sd->mBadTableFlag != 0) { + return 0; + } + + ReadCLen (Sd); + + Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16)(-1)); + if (Sd->mBadTableFlag != 0) { + return 0; + } + } + + Sd->mBlockSize --; + j = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)]; + + if (j >= NC) { + Mask = 1U << (BITBUFSIZ - 1 - 12); + + do { + if (Sd->mBitBuf & Mask) { + j = Sd->mRight[j]; + } else { + j = Sd->mLeft[j]; + } + + Mask >>= 1; + } while (j >= NC); + } + + // + // Advance what we have read + // + FillBuf(Sd, Sd->mCLen[j]); + + return j; +} + +//************************************************************************* +// +// +// Name: Decode +// +// Description: +// VOID Decode(IN OUT SCRATCH_DATA *Sd) decodes the source data and puts the +// resulting data into the destination buffer. +// +// Input: +// IN OUT SCRATCH_DATA *Sd +// The global scratch data. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// DecodeC +// +// Notes: +// +// +//************************************************************************* +STATIC +VOID +Decode ( + SCRATCH_DATA *Sd + ) +{ + UINT16 BytesRemain; + UINT32 DataIdx; + UINT16 c; + + BytesRemain = (UINT16)(-1); + + DataIdx = 0; + + for (;;) { + c = DecodeC (Sd); + if (Sd->mBadTableFlag != 0) { + return; + } + + if (c < 256) { + + // + // Process an Original character + // + + if (Sd->mOutBuf >= Sd->mOrigSize ) { + return; + } else { + Sd->mDstBase[Sd->mOutBuf ++] = (UINT8)c; + } + + } else { + + // + // Process a Pointer + // + + c = (UINT16)(c - (UINT8_MAX + 1 - THRESHOLD)); + + BytesRemain = c; + + DataIdx = Sd->mOutBuf - DecodeP(Sd) - 1; + + BytesRemain --; + while ((INT16)(BytesRemain) >= 0) { + Sd->mDstBase[Sd->mOutBuf ++] = Sd->mDstBase[DataIdx ++]; + if (Sd->mOutBuf >= Sd->mOrigSize) { + return; + } + BytesRemain --; + } + } + } + + return; +} + +//************************************************************************* +// +// +// Name: GetInfo +// +// Description: +// EFI_STATUS GetInfo(IN VOID *Source, IN UINT32 SrcSize, +// OUT UINT32 *DstSize, OUT UINT32 *ScratchSize) is the internal +// implementation of DECOMPRESS_PROTOCOL.GetInfo(). +// External consumers should use Decompress Protocol (not this function). +// +// Input: +// IN VOID *Source +// The source buffer containing the compressed data. +// +// IN UINT32 SrcSize +// The size of source buffer. +// +// OUT UINT32 *DstSize +// The size of destination buffer. +// +// OUT UINT32 *ScratchSize +// The size of scratch buffer. +// +// Output: +// EFI_SUCCESS, if the size of destination buffer and the size of +// scratch buffer are successull retrieved. +// EFI_INVALID_PARAMETER, if the source data is corrupted. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS +GetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +{ + UINT8 *Src; + + *ScratchSize = sizeof (SCRATCH_DATA); + + Src = Source; + if (SrcSize < 8) { + return EFI_INVALID_PARAMETER; + } + + *DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + return EFI_SUCCESS; +} + +//************************************************************************* +// +// +// Name: Decompress +// +// Description: +// EFI_STATUS Decompress(IN VOID *Source, IN UINT32 SrcSize, +// IN OUT VOID *Destination, IN UINT32 DstSize, IN OUT VOID *Scratch, +// IN UINT32 ScratchSize) is the internal implementation of +// DECOMPRESS_PROTOCOL.Decompress(). +// External consumers should use Decompress Protocol (not this function). +// +// Input: +// IN VOID *Source +// The source buffer containing the compressed data. +// +// IN UINT32 SrcSize +// The size of source buffer. +// +// IN OUT VOID *Destination +// The destination buffer to store the decompressed data. +// +// IN UINT32 DstSize +// The size of destination buffer. +// +// IN OUT VOID *Scratch +// The buffer used internally by the decompress routine. This buffer is +// needed to store intermediate data. +// +// IN UINT32 ScratchSize +// The size of scratch buffer. +// +// Output: +// EFI_SUCCESS, if the decompression is successfull. +// EFI_INVALID_PARAMETER, if the source data is corrupted. +// +// Modified: +// +// Referrals: +// FillBuf +// Decode +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS +Decompress ( + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ) +{ + UINT32 Index; + UINT32 CompSize; + UINT32 OrigSize; + EFI_STATUS Status; + SCRATCH_DATA *Sd; + UINT8 *Src; + UINT8 *Dst; + UINT8 PBit; + Status = EFI_SUCCESS; + Src = Source; + Dst = Destination; + + if (ScratchSize < sizeof (SCRATCH_DATA)) { + return EFI_INVALID_PARAMETER; + } + + Sd = (SCRATCH_DATA *)Scratch; + + if (SrcSize < 8) { + return EFI_INVALID_PARAMETER; + } + + CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24); + OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + + // + // If compressed file size is 0, return + // + + if (OrigSize == 0) { + return Status; + } + + if (SrcSize < CompSize + 8) { + return EFI_INVALID_PARAMETER; + } + + if (DstSize != OrigSize) { + return EFI_INVALID_PARAMETER; + } + + Src = Src + 8; + +// +// The length of the field 'Position Set Code Length Array Size' in Block Header. +// For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4 +// For Tiano de/compression algorithm(Version 2), mPBit = 5 +// + //assume Tiano decompression first. + //if decompression fails try with EFI decompression + for(PBit = 5; PBit>=4; PBit--){ + for (Index = 0; Index < sizeof(SCRATCH_DATA); Index++) { + ((UINT8*)Sd)[Index] = 0; + } + Sd->mSrcBase = Src; + Sd->mDstBase = Dst; + Sd->mCompSize = CompSize; + Sd->mOrigSize = OrigSize; + Sd->mPBit = PBit; + // + // Fill the first BITBUFSIZ bits + // + FillBuf(Sd, BITBUFSIZ); + + // + // Decompress it + // + + Decode (Sd); + + if (!Sd->mBadTableFlag) break; + } + + return (Sd->mBadTableFlag) ? EFI_INVALID_PARAMETER : EFI_SUCCESS; +} + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Library/EfiDBE.c b/Library/EfiDBE.c new file mode 100644 index 0000000..4830f29 --- /dev/null +++ b/Library/EfiDBE.c @@ -0,0 +1,891 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//************************************************************************* +// $Header: /Alaska/SOURCE/Core/Library/EfiDBE.c 7 7/10/09 4:32p Felixp $ +// +// $Revision: 7 $ +// +// $Date: 7/10/09 4:32p $ +//************************************************************************* +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/Library/EfiDBE.c $ +// +// 7 7/10/09 4:32p Felixp +// +// 6 7/10/09 4:01p Felixp +// Function headers added +// +// 5 9/04/07 10:20p Felixp +// +// 4 9/04/07 10:20p Felixp +// clean up +// +// 3 3/04/05 10:51a Mandal +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 12/23/04 9:42a Felixp +// +// 16 12/16/04 6:52a Felixp +// small improvemen in validation routine +// +// 15 8/26/04 9:27a Felixp +// +// 14 8/20/04 4:24p Felixp +// +// 13 8/20/04 3:42p Felixp +// +// 12 8/19/04 10:20a Felixp +// +// 11 5/05/04 2:33p Felixp +// +// 10 4/23/04 1:57p Felixp +// +// 9 4/16/04 4:23p Felixp +// +// 8 4/07/04 2:43p Felixp +// +// 7 4/07/04 12:46a Felixp +// REAL PLATFORM DEBUGGING (lots of bug fixes) +// +// 6 4/04/04 2:58p Felixp +// +// 5 3/26/04 1:19p Felixp +// +// 4 3/26/04 2:44a Felixp +// +// 3 3/26/04 2:22a Felixp +// +// 2 3/23/04 4:56p Felixp +// +// 1 3/23/04 3:24p Felixp +// +// 8 3/20/04 8:36p Felixp +// +// 7 3/20/04 10:46a Felixp +// +// 6 3/16/04 4:58p Felixp +// New DBE implementation +// +// 5 3/15/04 4:25p Felixp +// +// 4 3/03/04 5:04p Felixp +// +// 3 2/04/04 6:50p Yakovlevs +// +// 2 2/04/04 4:22p Yakovlevs +// +//************************************************************************* +// +// +// Name: EfiDBE.c +// +// Description: +// EFI Generic Database Engine serves all data storage, search and +// maintanance needs for Database Engine (DBE) objects. +// +// +//************************************************************************* +#include "AmiDxeLib.h" + +//Debug switch to verify database indexes integrity\after each database transaction. +//#define BDE_DBG_VERIFY 1 + +//************************************************************************* +//<_AMI_GHDR_START> +// +// Name: Database_Functions +// +// Description: +// A simple database API provided by the AMI library. +// +// Fields: Header Name Description +// ------------------------------------------------------------------ +// AmiDxeLib DBE_DATABASE +// AmiDxeLib DBE_KEY_FIELD +// None DbeBinSearch +// AmiDxeLib DbeInsert +// AmiDxeLib DbeLocateKey +// AmiDxeLib DbeGoToIndex +// AmiDxeLib DbeDelete +// +// Notes: +// Header details which header file contains the function prototype for +// the above functions; append .h to the given name. None indicates that +// no header file contains a function prototype. +// +//<_AMI_GHDR_END> +//************************************************************************* + +//************************************************************************* +//<_AMI_SHDR_START> +// +// Name: DBE_CMP +// +// Description: +// DBE_CMP is a function prototype structure for defining a function which +// takes in two records and returns: a positive INTN value if pRecord1 is +// greater than pRecord2, a negative INTN value if pRecord1 is less than +// pRecord2, or 0 if both records are equivalent. +// +// Input: +// +// Output: +// +// Modified: +// +// Referrals: +// Database_Functions +// +// Notes: +// Prototype provided in AmiDxeLib.h. See Database_Functions for example +// usage. +// +//<_AMI_SHDR_END> +//************************************************************************* + +//************************************************************************* +//<_AMI_SHDR_START> +// +// Name: DBE_KEY_FIELD +// +// Description: +// +// Fields: Name Type Description +// ------------------------------------------------------------------ +// RRcmp DBE_CMP +// KRcmp DBE_CMP +// pContext VOID* +// +// Referrals: +// Database_Functions +// +// Notes: +// Prototype provided in AmiDxeLib.h. See Database_Functions for example +// usage. +// +//<_AMI_SHDR_END> +//************************************************************************* + +//************************************************************************* +//<_AMI_SHDR_START> +// +// Name: DBE_DATABASE +// +// Description: +// Structure to hold database information. +// +// Fields: Name Type Description +// ------------------------------------------------------------------ +// MemoryType EFI_MEMORY_TYPE +// InitialCount UINTN Initial number of elements to allocate space for in the index array. +// RecordCount UINTN Number of records in database. +// KeyCount UINTN Number of keys in database. +// KeyField DBE_KEY_FIELD* +// IndexArray VOID* Address of the index array. +// +// Referrals: +// Database_Functions +// +// Notes: +// Prototype provided in AmiDxeLib.h. See Database_Functions for example +// usage. +// +//<_AMI_SHDR_END> +//************************************************************************* + +//************************************************************************* +// +// +// Name: OffsetRRCmp +// +// Description: +// OffsetRRCmp(IN VOID *pContext, IN VOID *pRecord1, IN VOID *pRecord2) +// compares two DBE records' keys and returns 0 if they are equal, non-zero +// if not. +// +// Input: +// IN VOID *pContext +// DBE_OFFSET_KEY_CONTEXT of this Database Engine (DBE). +// +// IN VOID *pRecord1 +// Pointer to the first record whose key is to be compared with pRecord2's +// key. +// +// +// IN VOID *pRecord2 +// Pointer to the second record whose key is to be compared with pRecord1's +// key. +// +// Output: +// INTN value of 0 if both records have the same key value; otherwise, +// returns non-zero value. +// +// Modified: +// +// Referrals: +// MemCmp +// +// Notes: +// +// +//************************************************************************* +INTN OffsetRRCmp( + IN VOID *pContext, VOID *pRecord1, VOID *pRecord2 +) +{ + DBE_OFFSET_KEY_CONTEXT *pOffsetKey = (DBE_OFFSET_KEY_CONTEXT*)pContext; + INT64 r; + switch (pOffsetKey->Size) + { + case 2: + r = (INT16)(*(UINT16*)((INT8*)pRecord1+pOffsetKey->Offset) - *(UINT16*)((INT8*)pRecord2+pOffsetKey->Offset)); + break; + case 4: + r = (INT32)(*(UINT32*)((INT8*)pRecord1+pOffsetKey->Offset) - *(UINT32*)((INT8*)pRecord2+pOffsetKey->Offset)); + break; + case 8: + r = *(UINT64*)((INT8*)pRecord1+pOffsetKey->Offset) - *(UINT64*)((INT8*)pRecord2+pOffsetKey->Offset); + break; + default: + return MemCmp((INT8*)pRecord1+pOffsetKey->Offset, + (INT8*)pRecord2+pOffsetKey->Offset, + pOffsetKey->Size + ); + } + return (r>0) ? 1 : (r<0) ? -1 : 0; +} + +//************************************************************************* +// +// +// Name: OffsetKRCmp +// +// Description: +// INTN OffsetKRCmp(IN DBE_OFFSET_KEY_CONTEXT *pContext, IN VOID *pKey, +// IN VOID *pRecord) compares a key with a record's key and returns 0 if +// they are equal, non-zero if not. +// +// Input: +// IN DBE_OFFSET_KEY_CONTEXT *pContext +// DBE_OFFSET_KEY_CONTEXT of this Database Engine (DBE). +// +// IN VOID *pKey +// Pointer to the key to be compared with pRecord's key. +// +// IN VOID *pRecord +// Pointer to the record whose key is to be compared with pKey's key. +// +// Output: +// INTN value of 0 if both keys have the same value; otherwise, returns +// non-zero value. +// +// Modified: +// +// Referrals: +// MemCmp +// +// Notes: +// +// +//************************************************************************* +INTN OffsetKRCmp( + IN DBE_OFFSET_KEY_CONTEXT *pContext, VOID *pKey, VOID *pRecord +) +{ + DBE_OFFSET_KEY_CONTEXT *pOffsetKey = (DBE_OFFSET_KEY_CONTEXT*)pContext; + INT64 r; + switch (pOffsetKey->Size) + { + case 2: + r = (INT16)(*(UINT16*)pKey - *(UINT16*)((INT8*)pRecord+pOffsetKey->Offset)); + break; + case 4: + r = (INT32)(*(UINT32*)pKey - *(UINT32*)((INT8*)pRecord+pOffsetKey->Offset)); + break; + case 8: + r = *(UINT64*)pKey - *(UINT64*)((INT8*)pRecord+pOffsetKey->Offset); + break; + default: + return MemCmp(pKey, + (INT8*)pRecord+pOffsetKey->Offset, + pOffsetKey->Size + ); + } + return (r>0) ? 1 : (r<0) ? -1 : 0; +} + +//************************************************************************* +// +// +// Name: AddrRRCmp +// +// Description: +// INTN AddrRRCmp(IN VOID* *pContext, IN VOID *pRecord1, IN VOID *pRecord2) +// compares two record pointers and returns 0 if they are equal, non-zero if +// not. +// +// Input: +// IN VOID **pContext +// Unused. +// +// IN VOID *pRecord1 +// Pointer to the first record to be compared. +// +// IN VOID *pRecord2 +// Pointer to the second record to be compared. +// +// Output: +// INTN value of 0 if both record pointers point to the same record; +// otherwise, returns non-zero value. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +INTN AddrRRCmp( + IN VOID* *pContext, VOID *pRecord1, VOID *pRecord2 +) +{ + return (UINTN)pRecord1-(UINTN)pRecord2; +} + +//************************************************************************* +// +// +// Name: AddrKRCmp +// +// Description: +// INTN AddrKRCmp(IN DBE_OFFSET_KEY_CONTEXT *pContext, IN VOID *pKey, +// IN VOID *pRecord) compares the a key and the address of a record and +// returns 0 if they are equal, non-zero if not. +// +// Input: +// IN DBE_OFFSET_KEY_CONTEXT *pContext +// Unused. +// +// IN VOID *pKey +// Pointer to the key to be compared. +// +// IN VOID *pRecord +// Pointer to the record to be compared. +// +// Output: +// INTN value of 0 if both the key's value and the address of the record are +// equal; otherwise, returns the key value minus the address of the record +// (*(UINTN*)pKey - pRecord). +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +INTN AddrKRCmp( + IN DBE_OFFSET_KEY_CONTEXT *pContext, VOID *pKey, VOID *pRecord +) +{ + return (UINTN)*(UINTN*)pKey-(UINTN)pRecord; +} + +//************************************************************************* +// +// +// Name: DbeBinSearch +// +// Description: +// VOID DbeBinSearch(IN DBE_DATABASE *Database, IN UINTN KeyNo, +// IN DBE_CMP Cmp, IN VOID *NewKey, OUT VOID **DataLocation, +// OUT INT8 *Vicinity, OUT INTN *RecordInd OPTIONAL) executes a binary +// search of the nearest location closest to the *NewKey value. If the +// DBE_KEY_FIELD structure of the database is NULL, the NewKey field is the +// address of the *Data; otherwise the NewKey field will be calculated as +// "(UINT8*)Data+KeyField.Offset" of "KeyField.Size" size. +// +// Input: +// IN DBE_DATABASE *Database +// Address of the database to be searched. +// +// IN UINTN KeyNo +// Starting key entry number. +// +// IN DBE_CMP Cmp +// Address of function which will be used to compare entries. +// +// IN VOID *NewKey +// Pointer to the Key Value we are comparing against. +// +// Output: +// OUT VOID **DataLocation +// Pointer to location within Index Array of desired data. +// +// OUT INT8 *Vicinity +// -1 if new entry should go before provided location, 0 if located, or 1 +// if new entry should follow the provided location. +// +// OUT INTN *RecordInd OPTIONAL +// If not NULL, provides the index position within Index Array of the +// desired data. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* + +VOID DbeBinSearch(IN DBE_DATABASE *Database, + IN UINTN KeyNo, + DBE_CMP Cmp, + IN VOID *NewKey, + OUT VOID **DataLocation, + OUT INT8 *Vicinity, + OUT INTN *RecordInd OPTIONAL) +{ +//-------------------------------------------------- + UINTN *IndexArray; + DBE_KEY_FIELD *KeyField = Database->KeyField+KeyNo; + INTN st=0,mid=0,end=Database->RecordCount-1; + INTN CmpResult; +//-------------------------------------------------- + IndexArray=(UINTN*)((UINTN)Database->IndexArray+Database->InitialCount*sizeof(VOID*)*KeyNo); + + if(!Database->RecordCount)*Vicinity=-1; + else{ + while(st<=end){ + mid=(st+end+1)/2; + CmpResult=Cmp(KeyField->pContext, NewKey, (VOID*)IndexArray[mid]); + if(!CmpResult ){ if(mid==end) break; st = mid; } + //New Key > Old Key we must go UP + else if(CmpResult>0) st=mid+1; + //New Key < Old Key we must go DOWN + else end=mid-1; + }//while //else + *Vicinity= (CmpResult > 0) ? 1 : (CmpResult < 0) ? -1 : 0; + } + *DataLocation=&IndexArray[mid]; + if(RecordInd)*RecordInd=(UINTN)mid; + return; +} + +//************************************************************************* +// +// +// Name: Validate +// +// Description: +// VOID Validate(IN DBE_DATABASE *Database) validates a Database Engine +// (DBE); ASSERTs if debug mode is on and any record within the DBE contains +// a key which is out of order from the other records. +// +// Input: +// IN DBE_DATABASE *Database +// Database to be validated. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// Only available if the BDE_DBG_VERIFY macro is defined as 1 in EfiDBE.c. +// +// +//************************************************************************* +#if defined(BDE_DBG_VERIFY) && BDE_DBG_VERIFY +VOID Validate(DBE_DATABASE *Database){ + UINTN i,j; + VOID **IndexArray = (VOID**)Database->IndexArray; + if (Database->RecordCount<2) return; + for (i=0;iKeyCount;i++){ + for(j=0;jRecordCount-1;j++) + ASSERT(Database->KeyField[i].RRcmp(Database->KeyField[i].pContext,IndexArray[j],IndexArray[j+1])<=0) + IndexArray+=Database->InitialCount; + } +} +#else +#define Validate(x) +#endif + +//************************************************************************* +// +// +// Name: DbeReallocIndexArray +// +// Description: +// EFI_STATUS DbeReallocIndexArray(IN DBE_DATABASE *Database) doubles +// the database's index array size by reallocating twice as much memory, +// copying the contents of the old memory to the new memory, and updating the +// necessary DBE_DATABASE members. +// +// Input: +// IN DBE_DATABASE *Database +// Database to have its index array doubled in size. +// +// Output: +// EFI_OUT_OF_RESOURCES, if the memory could not be allocated. +// EFI_INVALID_PARAMETER, if the previous index array was corrupted. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// MemSet +// MemCpy +// Validate +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS DbeReallocIndexArray(DBE_DATABASE *Database){ + VOID *New, *Old; + UINTN OldCount, NewCount, i; + EFI_STATUS Status; +//------------------------ + Validate(Database); + Old=Database->IndexArray; + OldCount=Database->InitialCount; + NewCount = OldCount * 2; + Status=pBS->AllocatePool(Database->MemoryType,NewCount*sizeof(VOID*)*Database->KeyCount,&New); + if(EFI_ERROR(Status)) return Status; + MemSet(New,NewCount*sizeof(VOID*)*Database->KeyCount,0); + for(i=0; iKeyCount; i++) + MemCpy((VOID**)New + NewCount*i, + (VOID**)Old + OldCount*i, + OldCount*sizeof(VOID*) + ); + Database->IndexArray = New; + Database->InitialCount = Database->InitialCount*2; + Status=pBS->FreePool(Old); + Validate(Database); + return Status; +} + +//************************************************************************* +// +// +// Name: DbeInsert +// +// Description: +// EFI_STATUS DbeInsert(IN DBE_DATABASE *Database, IN VOID *Record) inserts +// a user provided record into a database. +// +// Input: +// IN DBE_DATABASE *Database +// The database to be inserted into. +// +// IN VOID *Record +// The record to insert into Database. +// +// Output: +// EFI_INVALID_PARAMETER, if Database, Record, or Database->KeyField are +// NULL. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// DbeReallocIndexArray +// DbeBinSearch +// MemCpy +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS DbeInsert(DBE_DATABASE *Database,VOID* Record){ + UINTN i; + EFI_STATUS Status = EFI_SUCCESS; +//---------------------------- + if((!Database)||(!Record)) return EFI_INVALID_PARAMETER; + + if((Database->InitialCount-1)==Database->RecordCount){ + Status=DbeReallocIndexArray(Database); + if(EFI_ERROR(Status)) return Status; + } + + if(!Database->KeyField)return EFI_INVALID_PARAMETER; + for (i=0;iKeyCount;i++){ + INTN RecordIndex; + DBE_KEY_FIELD *KeyField; + INT8 Vicinity; + VOID *ptr; + + KeyField=Database->KeyField+i; + //Search for the key... + DbeBinSearch(Database,i,KeyField->RRcmp, Record, &ptr,&Vicinity,&RecordIndex); + + //if we stoped at the position but the "NewKey" we are about to insert bigger then the + //OldKey referenced by the "pos" NewKey has to be inserted after the pos. In case of + //lesser or equal it must be inserted at the current position + if(Vicinity>=0){ + RecordIndex++; + ((UINTN*)ptr)++; + } + MemCpy((VOID*)(((UINTN*)ptr)+1),ptr,sizeof(UINTN)*(Database->RecordCount-RecordIndex)); + *(UINTN*)ptr=(UINTN)Record; + } + Database->RecordCount++; + Validate(Database); + return Status; +} + +//************************************************************************* +// +// +// Name: DbeLocateKey +// +// Description: +// EFI_STATUS DbeLocateKey(IN DBE_DATABASE *Database, IN UINTN KeyNo, +// IN VOID *KeyValue, OUT VOID **Record, OUT INT8 *Vicinity, +// OUT UINTN *RecordIndex OPTIONAL) locates a record by its key in a +// database. +// +// Input: +// IN DBE_DATABASE *Database +// Database to locate the key within. +// +// IN UINTN KeyNo +// Key entry number to start searching from. For example, 0 starts from the +// the first key entry; 1 starts from the second. +// +// IN VOID *KeyValue +// Pointer to the key to search for. +// +// OUT VOID **Record +// Output location for the pointer to the record which maps to the provided key. +// +// OUT INT8 *Vicinity +// Relative location of the KeyValue in respect to the returned Record. For +// instance, 0 means that the Record uses KeyValue, 1 means Record is the +// next highest entry above the desired KeyValue, and -1 means Record is the +// previous entry. This should be 0 if the key was located. +// +// OUT UINTN *RecordIndex OPTIONAL +// Index position within Index Array of desired record pointer. +// +// Output: +// EFI_INVALID_PARAMETER, if Database, Record, or Database->KeyField are +// NULL; also if KeyNo > Database->KeyCount - 1. +// EFI_NOT_FOUND, if key not found. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// DbeBinSearch +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS DbeLocateKey(IN DBE_DATABASE *Database, + IN UINTN KeyNo, + IN VOID *KeyValue, + OUT VOID **Record, + OUT INT8 *Vicinity, + OUT UINTN *RecordIndex OPTIONAL) +{ +//--------------------------------------------------------- + //Don't do extra stuff + if((!Database)||(!Record))return EFI_INVALID_PARAMETER; + if((!Database->KeyField)||(KeyNo>Database->KeyCount-1)) return EFI_INVALID_PARAMETER; + + DbeBinSearch(Database,KeyNo,Database->KeyField[KeyNo].KRcmp,KeyValue,Record,Vicinity,RecordIndex); + + if(*Vicinity==0)return EFI_SUCCESS; + else return EFI_NOT_FOUND; +} + +//************************************************************************* +// +// +// Name: DbeGoToIndex +// +// Description: +// EFI_STATUS DbeGoToIndex(IN DBE_DATABASE *Database, IN UINTN KeyNo, +// IN INTN Index, OUT VOID **Record) returns the record pointer at the user +// provided index inside Database's IndexArray. +// +// Input: +// IN DBE_DATABASE *Database +// Database to fetch the record pointer from. +// +// IN UINTN KeyNo +// The key number of the desired IndexArray. +// +// IN INTN Index +// The index within the IndexArray to retrieve the record pointer from. +// +// OUT VOID **Record +// Filled with the address of the record pointer associated with the provided +// Index. +// +// Output: +// EFI_DBE_EOF, if Index is negative or exceeds the number of valid +// records. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS DbeGoToIndex( + IN DBE_DATABASE *Database, + IN UINTN KeyNo, + IN INTN Index, + OUT VOID **Record) +{ + UINTN *IndexArray; +//----------------------------------------------------- + IndexArray=(UINTN*)((UINTN)Database->IndexArray+Database->InitialCount*sizeof(VOID*)*KeyNo); + + if((UINTN)Index>=Database->RecordCount) { + if (Database->RecordCount) + *Record=(VOID*)IndexArray[Database->RecordCount-1]; + return EFI_DBE_EOF; + } + if(Index<0) { + *Record=(VOID*)IndexArray[0]; + return EFI_DBE_BOF; + } + + *Record=(VOID*)IndexArray[Index]; + return EFI_SUCCESS; +} + +//************************************************************************* +// +// +// Name: DbeDelIndexKeyEntry +// +// Description: +// EFI_STATUS DbeDelIndexKeyEntry(IN DBE_DATABASE *Database, IN UINTN KeyNo, +// IN VOID *Data) deletes a record entry in Database associated with KeyNo +// containing Data. +// +// Input: +// IN DBE_DATABASE *Database +// Database to delete the provided Data from. +// +// IN UINTN KeyNo +// Key number within the Database to delete the Data from. +// +// IN VOID *Data +// The data associated with the record to be deleted from Database. +// +// Output: +// EFI_INVALID_PARAMETER, if the desired Data to be deleted could not be +// located. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// MemCpy +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS DbeDelIndexKeyEntry(IN DBE_DATABASE *Database, IN UINTN KeyNo, IN VOID* Data){ + UINTN RecordIndex; + VOID **IndexArray, **ptr; +//------------------------------------ + IndexArray=(VOID**)((UINTN)Database->IndexArray+Database->InitialCount*sizeof(VOID*)*KeyNo); + for(RecordIndex=0; RecordIndex < Database->RecordCount && IndexArray[RecordIndex]!=Data; RecordIndex++); + if(IndexArray[RecordIndex]!=Data) return EFI_INVALID_PARAMETER; + ptr = IndexArray+RecordIndex; + MemCpy(ptr,ptr+1,sizeof(VOID*)*(Database->RecordCount-RecordIndex-1)); + return EFI_SUCCESS; +} + +//************************************************************************* +// +// +// Name: DbeDelete +// +// Description: +// EFI_STATUS DbeDelete(IN DBE_DATABASE *Database, IN VOID *Data, +// IN BOOLEAN FreeData) removes all records associated with the user +// provided Data pointer. Function assumes every keyIf FreeData is TRUE, it will also FreePool the +// Data when it is done. +// +// Input: +// IN DBE_DATABASE *Database +// Database to remove the associated records from. +// +// IN VOID *Data +// Data to check +// IN BOOLEAN FreeData +// +// Output: +// EFI_INVALID_PARAMETER, if the provided Database is empty. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// DbeDelIndexKeyEntry +// Validate +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS DbeDelete(IN DBE_DATABASE *Database, IN VOID* Data, IN BOOLEAN FreeData){ + INTN KeyNo; + EFI_STATUS Status=EFI_SUCCESS; +//------------------------------------ + if (!Database->RecordCount) return EFI_INVALID_PARAMETER; + for (KeyNo=0; KeyNo<(INTN)Database->KeyCount; KeyNo++){ + Status=DbeDelIndexKeyEntry(Database,KeyNo,Data); + if(EFI_ERROR(Status)) return Status; + } + Database->RecordCount--; + if(FreeData) pBS->FreePool(Data); + Validate(Database); + return Status; +} +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Library/EfiLib.c b/Library/EfiLib.c new file mode 100644 index 0000000..f937c89 --- /dev/null +++ b/Library/EfiLib.c @@ -0,0 +1,4779 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2012, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Library/EfiLib.c 3 4/16/14 3:11a Chaseliu $ +// +// $Revision: 3 $ +// +// $Date: 4/16/14 3:11a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Library/EfiLib.c $ +// +// 3 4/16/14 3:11a Chaseliu +// [TAG] EIP163569 +// [Category] Improvement +// [Description] Update for support 2014 BIOS Security Disclosures. +// [Files] +// Library\PeiLib.c +// Library\EfiLib.c +// Core\EM\NVRAM\NVRAMDXE.c +// Core\EM\Capsule2_0\Capsule2_0.c +// Core\CORE_DXE\FwVolBlock.c +// +// 112 2/28/14 5:41p Artems +// EIP 154195 Fixed vulnerability where memory pointer was stored in NVRaM +// and may be compromised +// +// 109 7/19/12 6:00p Felixp +// Enhacement: +// IsValidDevicePath is updated to make sure that device path node length +// is not less than +// sizeof(EFI_DEVICE_PATH_PROTOCOL). +// This prevents dead loops on device path nodes with a zero length. +// +// 108 7/12/12 5:22p Oleksiyy +// [TAG] EIP95266 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Build error in AmiFillFpdt function +// [RootCause] multiplying 64 bit values with the help of "*" operator +// [Solution] Mul64() function is used now +// [Files] EfiLib.c +// +// 107 6/12/12 3:24p Oleksiyy +// TAG] EIP90322 +// [Category] Improvement +// [Description] Extern declaradion of gAmiGlobalVariableGuid moved to +// AmiLib.h. +// [Files] AmiLib.h, Misc.c, EfiLib.c, AcpiCore.c and S3Resume.c +// +// 106 6/12/12 11:19a Oleksiyy +// [TAG] EIP88889 +// [Category] Improvement +// [Description] FACP ver 5.0 structure added, FPDT mesurment accuracy +// improved. +// [Files] ACPI50.h, ACPI.sdl, AcpiCore.c, S3Resume.c, Image.c, +// EfiLib.c +// +// 105 5/22/12 4:27p Oleksiyy +// [TAG] EIP90322 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] ChiefRiver SCT Fail, improper variable FPDT_Variable in +// ACPI module +// [RootCause] EFI_GLOBAL_VARIABLE guid is used in non EFI defined +// variable. +// [Solution] New guig AMI_GLOBAL_VARIABLE_GUID is created and used. +// [Files] AmiLib.h, Misc.c, EfiLib.c, AcpiCore.c and S3Resume.c +// +// 104 4/30/12 3:57p Artems +// [TAG] EIP N/A +// [Category] Improvement +// [Description] Modified GraphicsConsole driver to output whole string +// instead of symbol-by-symbol output +// [Files] Gc.c, AmiDxeLib.h, EfiLib.c, UefiHiiUtils.c +// +// 103 4/12/12 3:01p Artems +// [TAG] EIP N/A +// [Category] Improvement +// [Description] System may deadlock when parsing corrupted device path. +// Added function to validate device path before using in LoadImage +// [Files] Image.c EfiLib.c +// +// 102 2/22/12 12:17p Oleksiyy +// [TAG] EIP83714 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] S3 resume failure when using EFI_S3_SAVE_STATE_PROTOCOL +// [RootCause] GUID in _GetBootScriptSaveInterface was redefined in +// different file and because of this wrong protocol was located and +// _GetBootScriptSaveInterface was working incorrectly. +// [Solution] Declaration of GUID in _GetBootScriptSaveInterface +// function in EfiLib.c change to use unique name and static. +// [Files] EfiLib.c +// +// 101 11/11/11 5:28p Oleksiyy +// [TAG] EIP64296 +// [Category] New Feature +// [Description] Creation and filling of Firmware Performance Data Table +// is added. FirmPerfDataTab.h renamed to ACPI50.h +// [Files] AcpiCore.c, EfiLib.c, S3Resume.c and ACPI50.h added. +// +// 100 11/08/11 5:20p Oleksiyy +// [TAG] EIP64296 +// [Category] New Feature +// [Description] Creation and filling of Firmware Performance Data Table +// is added. +// [Files] AcpiCore.c, AmiDxeLib.h, CSM.c, DxeMain.c, EfiLib.c, +// Image.c, S3Resume.c and FirmPerfDataTab.h +// +// 99 10/24/11 5:38p Artems +// EIP 70530: Fixed bug reported by SCT 2.3.1 for TW plugfest. +// Function compare languages should ignore case as per RFC 4646 +// +// 98 10/20/11 5:15p Oleksiyy +// [TAG] EIP72806 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Runtime status code hangs +// [RootCause] Not converting actual status code functions addresses on +// Virtual Address Change event. +// [Solution] Status code functions converted. +// [Files] EfiLib.c, StatusCode.sdl and StatusCodeRuntime.c +// +// 97 7/18/11 3:43p Felixp +// Enhancement: InitSmmHandlerPi is updated to remove dependency on +// SmmBase2 (SmmBasePi) from the not-in-SMM branch. +// +// 96 7/13/11 3:06p Felixp +// Undo pElement->pPrev initialization introduced by prev. check in. It is +// not required. +// +// 95 7/13/11 2:50p Felixp +// Bug fixes in DListInsert(EIP64811): +// - The function corrupted the memory if pAfter was the last element in +// the list. +// - pElement->pPrev was not initialized. +// +// 94 6/24/11 1:45p Felixp +// _GetBootScriptSaveInterface function is added. +// +// 93 6/16/11 9:28a Felixp +// Enhancements: SMM-related functions and global variables are split into +// Framework and PI instances. Proper instance is selected based on +// supported version of the PI specification and module type. +// +// 92 5/19/11 2:25p Artems +// EIP 60634: Modified DPCreateNode function to fill allocated buffer with +// zeroes before using it +// +// 91 3/17/11 4:58p Felixp +// Enhancement: FindDeviceName functions is updated with +// a workaround for mass storage devices that have no partition +// (floppy or USB key formatted as floppy). The name for these devices +// is provided by more than one driver. +// One of the name sources if file system driver. It provides a name like +// "FAT File System", +// which is not very interesting. The real device name like "Kingston +// DataTreveler" +// (that comes from other driver) is far more useful. +// This workaround is to ignore name returned by a consumer of the disk +// I/O protocol, +// which is a file system driver. +// +// 90 2/05/11 3:17p Artems +// Added helper function to initialize global pointers in SMM +// Replaced FirmwareVolume protocol with FirmwareVolume2 protocol +// +// 89 10/07/10 12:30p Felixp +// USE_DXE_STATUS_CODE_INSTANCE_IN_SMM SDL token support is added. +// +// 88 10/06/10 5:01p Felixp +// LibInitStatusCodePtr is updated not to call LocateProtocol from SMM +// +// 87 10/01/10 4:38p Oleksiyy +// Issue Number: 39752 +// +// Category: Improvement +// +// Description: Runtime trace support added. +// +// Files: Files: Uart1.asl, Tokens.c, Runtime.c, GenericSio.c, EfiLib.c, +// CsmLib.c, AmiDxeLib.h and StatusCode eModule. +// +// 85 9/02/10 11:16a Felixp +// Enhancement: do not use pRS in AmiLibGoVirtual; +// the pointer may have already been already converted to the virtual +// address by the library consumer. +// Use the internal library copy instead. +// +// 84 8/23/10 3:30p Felixp +// Enhancement(EIP 29307, 39752): AMI DXE library is updated to handle +// runtime +// and SMM instances of the status code protocol. +// +// 83 5/25/10 11:12a Felixp +// Bug fix in the TimerStart function +// +// 82 3/12/10 10:28a Felixp +// Bug fix: Potential UEFI OS Problem; +// pRS pointer has been in used in AmiLibGoVirtual function after +// virtualization. +// +// 81 2/23/10 10:16p Felixp +// HiiLibSetBrowserData function is added +// +// 80 11/25/09 1:30p Felixp +// Trace functions is updated to suppress Trace message +// if message Level defined by the first parameter is disabled using +// TRACE_LEVEL_MASK SDL token. +// +// 79 11/25/09 12:00p Felixp +// Behavior of GetImageName and GetControllerName functions in UEFI 2.1 +// mode is extended. +// The functions will now use ComponentName protocol if ComponentName2 +// protocol is not available. +// +// 78 11/24/09 10:41a Felixp +// +// 77 10/28/09 4:21p Felixp +// ReadImage function is updated. Temporary buffer was not deallocated(EIP +// 28575). +// +// 76 10/21/09 2:52p Felixp +// +// 74 10/14/09 10:41p Felixp +// +// 73 10/09/09 4:54p Felixp +// UEFI 2.1-related changes: +// 1. Library files are update to support Framework and UEFI 2.1 HII +// (based on EFI_SPECIFICATION_VERSION value). +// 2. GetDefaultLang function is no longer supported +// 3. New HII-related functions are added +// (the functions support both Framework and UEFI HII): +// HiiLibGetString, HiiLibSetString, HiiLibPublishPackages, +// HiiLibGetBrowserData. +// +// 72 8/21/09 2:50p Felixp +// 1. LanguageCodesEqual function is added. +// The function compares language codes in the format appropriate +// for the supported version of UEFI sepcification +// (defined by EFI_SPECIFICATION_VERSION SDL token). +// 2. Component Name related library functions are updated to support +// both ComponentName and ComponentName2 protocols. +// +// 71 8/05/09 12:23p Yakovlevs +// Fixed TRACE Size issue to work with IA32 mode. +// +// 70 7/30/09 4:37p Vyacheslava +// Fixed comments. +// +// 69 7/28/09 4:46p Vyacheslava +// Bug fix. EIP#24453: Synopsis: CPU exception when printing long debug messages. +// +// 68 7/23/09 11:17a Yakovlevs +// Fixed issue in LibAllocCspResource function with IO ONLY resources (EIP +// 24323). +// +// 67 7/10/09 4:32p Felixp +// +// 66 7/10/09 4:01p Felixp +// Function headers added +// +// 65 6/05/09 6:32p Yakovlevs +// Fixed issue in LibAllocCspResources when RT attributes were acidentaly +// cleared. +// +// 64 5/21/09 4:49p Felixp +// New function InitAmiRuntimeLib is added. +// The function can be used by Runtime drivers to initialize library +// (the function calls InitAmiLib) and register callbacks +// on exit boot services and virtual address change events. +// +// 63 5/14/09 5:26p Felixp +// +// 62 5/14/09 9:32a Felixp +// New feature: SMM version of Runtime Services +// InitSmmHandler function is updated ot override pRS with the SMM +// instance of RS table. +// New functions +// InitSmmHandlerEx and GetSmstConfigurationTable area added +// +// 61 5/04/09 4:08p Felixp +// GetControllerName function is updated to search +// for controller name using handlers of all ancestors of the given +// controller +// (used to be just immediate parent). +// +// 60 12/16/08 1:24a Iminglin +// The function value of TimerStart for compliance. +// +// 59 10/07/08 12:53p Artems +// Minor improvements of WritePerformanceDataToOS function +// +// 58 9/30/08 12:15a Felixp +// +// 57 9/30/08 12:10a Felixp +// +// 56 9/30/08 12:07a Felixp +// WriteBootToOsPerformanceData function added +// +// 55 6/06/08 10:56a Felixp +// Bug fix in DPCut routine +// +// 54 5/06/08 10:05a Felixp +// Performance API added +// +// 53 10/22/07 6:29p Felixp +// Bug fix in DListInsert library routine. Size field of the DLIST +// structure was not updated. +// +// 52 9/04/07 12:09p Felixp +// TheImageHandle global variable is added. The variable is initialized in +// the InitAmiLib routine with the current image handle. +// +// 51 8/30/07 11:04p Felixp +// GetBootMode routine is added. The routine can be used by DXE/EFI +// modules to get current boot mode. +// +// 50 8/02/07 1:36a Felixp +// Always define Trace and GetImageName routines (used to be only when +// EFI_DEBUG is defined). This is needed to support selective debugging. +// +// 49 5/22/07 3:42p Felixp +// Bug fix in LibAllocCspResource: runtime attribute has been ignored. +// It caused stop error 1E early during EFI Longhorn Server installation. +// +// 48 5/14/07 7:35p Yakovlevs +// +// 47 5/14/07 7:30p Yakovlevs +// Improved AllocateCSPResource() function logic. +// +// 46 4/19/07 12:36p Felixp +// New functions added: LibGetDxeSvcTbl and LibAllocateCspResource +// LibAllocateCspResource replaces AllocCspResource +// AllocCspResource preserved for backward compatibility. +// +// 44 4/17/07 10:54a Yakovlevs +// AllocCspResource function preserved for compatibility witn core 4.5.3 +// +// 43 4/13/07 6:17p Yakovlevs +// Functions LibGetDxeSvcTbl() and LibAllocCspResource() was added +// +// 41 3/30/07 4:53p Felixp +// 1. DPAddNode, DPAdd updated to handle NULL parameters in accordance +// with UEFI2.0 Errata. +// 2. DPLength update: protection from junk data added. +// +// 40 10/13/06 12:23p Felixp +// +// 39 10/13/06 12:20p Felixp +// +// 38 10/13/06 9:32a Felixp +// +// 37 10/13/06 9:28a Felixp +// UEFI2.0 compliant invalid handling of parameters in DPxxx routines +// +// 36 10/13/06 12:17a Felixp +// Device Path functions updated to correctly handle invalid parameters +// +// 35 10/12/06 6:44p Felixp +// DPNextInstance, DPCreateNode, DPIsMultiInstance functions added +// +// 34 10/12/06 9:40a Felixp +// CreateLegacyBootEvent & CreateReadyToBootEvent functions added +// +// 33 10/07/06 10:21a Felixp +// UEFI2.0 compliance: pRT->ReportStatusCode changed to +// StatusCodePtr->ReportStatusCode +// +// 32 9/08/06 9:25a Felixp +// +// 31 8/24/06 9:27a Felixp +// Preliminary x64 support (work in progress) +// +// 30 5/23/06 4:10a Felixp +// GetImageName function improved +// +// 29 5/19/06 10:28p Felixp +// Updated to use NEXT_NODE & NODE_LENGTH macros +// +// 28 3/13/06 1:52a Felixp +// +// 27 11/16/05 11:07a Yakovlevs +// DPCmp(), DPCut() functions added +// +// 26 11/11/05 11:45a Markw +// Renamed IntallSmmHandler to InitSmmHandler because of build errors +// because another driver used InstallSmmHandler. +// +// 25 11/11/05 11:38a Felixp +// GetControllerName function added +// +// 24 11/08/05 5:58p Markw +// Created InstallSmiHandler library function. +// +// 23 11/07/05 10:33a Felixp +// ReadImage improvements: If file path is +// MEDIA_FV_FILEPATH_DP and +// no FV device specified, function will scan all FVs trying to locate the +// file. +// +// 22 6/29/05 10:41a Yakovlevs +// +// 21 6/28/05 6:47p Yakovlevs +// Function AllocCspResources added +// +// 20 6/03/05 3:43p Yakovlevs +// Added DPGetLastNode(EFI_DEVICE_PATH_PROTOCOL *pDp) function +// +// 19 4/06/05 9:34a Felixp +// function LoadStrings added +// +// 18 4/04/05 7:29p Felixp +// +// 16 4/04/05 2:59p Felixp +// LoadResources function added +// +// 15 4/04/05 9:32a Felixp +// Small inprovements in GetEfiVariable +// +// 14 3/25/05 11:32a Felixp +// RegisterProtocolCallback function added +// +// 13 3/17/05 6:35p Felixp +// +// 12 3/17/05 1:29p Felixp +// ReadImageResource function added +// +// 11 3/04/05 10:52a Mandal +// +// 10 3/03/05 12:30p Felixp +// GetDefaultLang added +// +// 9 2/11/05 5:55p Felixp +// New DevicePath function added(DPAddNode, DPAddInstance). +// Implementation of DPLength and DPAdd improved. +// +// 8 2/08/05 5:24p Felixp +// Parameter added to DPIsOneOf. +// +// 7 2/07/05 5:21p Felixp +// GetEfiVariable funciton added +// +// 6 2/07/05 4:09p Yakovlevs +// MallocZ function added - Allocates "0x00" filled Pool. +// +// 5 2/03/05 7:59p Felixp +// DPIsOneOf function added +// +// 4 1/28/05 1:06p Felixp +// InitAmiLib change to ignore second call +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 12/23/04 9:42a Felixp +// +// 31 12/21/04 4:58p Markw +// Modified device path defines for consistency. +// +// 30 12/17/04 7:24p Olegi +// PrintDebugMessageVaList added +// +// 29 11/24/04 9:37a Felixp +// GetImageName extended to use ComponentName protocol +// +// 28 11/19/04 1:33a Felixp +// GetImageName debug routine added (image name by image handle) +// +// 27 11/18/04 6:09p Felixp +// FindNextHobByType deleted (moved to AmiLib(Misc.c)) +// +// 26 11/10/04 5:16p Felixp +// Level parameter added to Trace fucntion +// +// 25 10/22/04 7:42p Felixp +// +// 24 8/28/04 1:49a Felixp +// NVRAM Routines fixes +// +// 23 8/23/04 3:12p Felixp +// +// 22 8/20/04 6:34p Felixp +// +// 21 8/20/04 11:49a Felixp +// +// 20 8/18/04 3:16p Felixp +// +// 19 7/21/04 8:16p Yakovlevs +// +// 18 7/16/04 3:57p Felixp +// Changes to support both 7f and ff values for the device path end type +// +// 17 7/13/04 10:42a Felixp +// +// 16 4/22/04 5:39p Markw +// Changed FvReadFile to FvReadPe32Image and fixed ReadFile. +// +// 15 4/22/04 12:15p Markw +// Fixed FvReadFile. +// +// 14 4/17/04 4:23p Felixp +// +// 13 4/14/04 4:18p Markw +// Using EFI_ERROR. +// +// 12 4/14/04 11:37a Markw +// Fixed FvReadFile. Now frees correct Buffer. +// +// 11 4/14/04 11:02a Markw +// Added FvReadFile. +// +// 6 4/07/04 12:46a Felixp +// REAL PLATFORM DEBUGGING (lots of bug fixes) +// +// 3 3/29/04 5:27p Markw +// Added a function to print debug messages. +// +//********************************************************************** +// +// +// Name: EfiLib.c +// +// Description: +// Contains generic EFI library functions. +// +// +//************************************************************************* +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if SMM_SUPPORT +#include +#endif +#include +#include +#include + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_SYSTEM_TABLE *pST=NULL; +GLOBAL_REMOVE_IF_UNREFERENCED EFI_BOOT_SERVICES *pBS=NULL; +GLOBAL_REMOVE_IF_UNREFERENCED EFI_RUNTIME_SERVICES *pRS=NULL; +GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_BASE_PROTOCOL *pSmmBaseFramework=NULL; +GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_SYSTEM_TABLE *pSmstFramework=NULL; +#if PI_SPECIFICATION_VERSION >= 0x0001000A +GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_BASE2_PROTOCOL*pSmmBasePi=NULL; +GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_SYSTEM_TABLE2 *pSmstPi=NULL; +#endif +GLOBAL_REMOVE_IF_UNREFERENCED DXE_SERVICES *pDxe=NULL; +GLOBAL_REMOVE_IF_UNREFERENCED EFI_HANDLE TheImageHandle=NULL; +GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID guidFS = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; +GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID guidFileInfo = EFI_FILE_INFO_ID; +GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID guidLoadFile = EFI_LOAD_FILE_PROTOCOL_GUID; +GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID guidDevicePath = EFI_DEVICE_PATH_PROTOCOL_GUID; +GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID guidFV = EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID; +GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID guidDxeSvcTbl = DXE_SERVICES_TABLE_GUID; + +extern EFI_GUID gEfiLoadedImageProtocolGuid; +extern EFI_GUID gEfiComponentName2ProtocolGuid; +#if EFI_SPECIFICATION_VERSION<=0x20000 +//for backward compatibility +GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID guidHII = EFI_HII_PROTOCOL_GUID; +#endif +#if EFI_SPECIFICATION_VERSION>=0x20000 +extern EFI_GUID gEfiStatusCodeRuntimeProtocolGuid; +static EFI_STATUS_CODE_PROTOCOL *StatusCodePtr = NULL; +#endif +#if SMM_SUPPORT +static EFI_SMM_STATUS_CODE_PROTOCOL *StatusCodeSmmPtr = NULL; +#endif +GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID SmmRsTableGuid = EFI_SMM_RUNTIME_SERVICES_TABLE_GUID; + +static BOOLEAN IsAtRuntime = FALSE; +static BOOLEAN IsInVirtualMode = FALSE; +static BOOLEAN IsInSmm = FALSE; + +//************************************************************************* +// +// +// Name: Device_Path_Functions +// +// Description: +// Device path related functions defined in the AMI library. +// +// Fields: Header Function Description +// ------------------------------------------------------------------ +// AmiDxeLib DPLength Find the size of a device path in bytes. +// AmiDxeLib DPAddNode Create new device path with the contents of one device path + the first element from another. +// AmiDxeLib DPAdd Create new device path by appending a device path's elements to another device path. +// AmiDxeLib DPAddInstance Create new device path utilizing two provided device paths as instances. +// AmiDxeLib DPCopy Create new device path containing the exact contents of another device path. +// AmiDxeLib DPIsOneOf Determine whether a device path contains a user provided device path. +// AmiDxeLib DPGetLastNode Return the last node of a device path prior to END_OF_DEVICE_PATH. +// AmiDxeLib DPCmp Determine whether two device paths are equivalent. +// AmiDxeLib DPCut Create new device path with all but the last node of another device path. +// AmiDxeLib DPGetEndNode Return the last node of a device path. +// AmiDxeLib DPNextInstance Create a copy of the current device path instance and updates the device path to point to the next instance. +// AmiDxeLib DPCreateNode Create a device path node. +// AmiDxeLib DPIsMultiInstance Determine whether device path is single or multi-instance. +// +// Notes: +// Header details which header file contains the function prototype for +// the above functions. Append .h to the given name. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: Performance_Measurement_Functions +// +// Description: +// Functions which are used to measure boot performance that are defined in +// the AMI library. +// +// Fields: Header Function Description +// ------------------------------------------------------------------ +// AmiPeiLib PEI_PERF_START Macro that starts timing for performance measurement. +// AmiPeiLib PEI_PERF_END Macro that stops timing for performance measurement. +// AmiPeiLib PeiPerfMeasure Start or stop timing performance measurement. +// AmiDxeLib PERF_START Macro that starts timing for performance measurement. +// AmiDxeLib StartMeasure Start timing for performance measurement. +// AmiDxeLib PERF_END Macro that stops timing for performance measurement. +// AmiDxeLib EndMeasure Stop timing for performance measurement. +// AmiDxeLib PERF_CODE Macro that inserts performance measurement related code. +// AmiPeiLib PEI_PERF_SAVE_S3_DATA Macro that saves performance information to a HOB for S3 measurement. +// AmiPeiLib SaveS3PerformanceData Save performance information to a HOB for S3 measurement. +// AmiDxeLib WriteBootToOsPerformanceData Write performance information. +// +// Notes: +// Header details which header file contains the function prototype for +// the above functions. Append .h to the given name. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: Doubly_Linked_List_Functions +// +// Description: +// The following functions are provided by the AMI library as a basic API for +// a doubly-linked list. Note that the DLINK node structure does not include +// an entry for the actual data. There are several methods for getting +// around this limitation. +// +// The easiest method is to create a new structure type which contains +// a DLINK structure as its first member and the data afterwards. This new +// structure can then be typecasted to the old DLINK type when using the +// API. See notes for an example. +// +// There are presently no search functions provided for this API. +// +// Fields: Header Name Description +// ------------------------------------------------------------------ +// AmiDxeLib DLIST Doubly-linked list structure. +// AmiDxeLib DLINK Doubly-linked list node. +// AmiDxeLib DListInit Initialize a DLIST list structure. +// AmiDxeLib DListAdd Add a DLINK node to the end of a DLIST. +// AmiDxeLib DListDelete Remove a DLINK node from a DLIST. +// AmiDxeLib DListInsert Insert a DLINK node after a specific DLINK node inside a DLIST. +// AmiDxeLib DListEmpty Determine whether a DLIST is empty. +// +// Notes: +// Header details which header file contains the function prototype for +// the above functions; append .h to the given name. None indicates that +// no header file contains a function prototype. +// +// The following code demonstrates creating a node which +// contains a UINT32 data member, inserting it into a list, then changing +// its value. +// +// typedef struct { +// DLINK Link; +// UINT32 Data; +// } UINT32_NODE; +// +// DLIST ExampleList; +// UINT32_NODE ExampleNode; +// +// ExampleNode.Data = 0xDEADBEEF; +// +// DListInit(&ExampleList); +// DListAdd(&ExampleList, (DLINK*) &ExampleNode); +// ((UINT32_NODE*)ExampleList.pHead)->Data = 0x12345678; +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: InitAmiLib +// +// Description: +// VOID InitAmiLib(IN EFI_HANDLE ImageHandle, +// IN EFI_SYSTEM_TABLE *SystemTable) initializes the global variables used by +// library routines. It must be called before any other library routine is +// used. See notes for variables initialized. +// +// Input: +// IN EFI_HANDLE ImageHandle +// The image handle. +// +// IN EFI_SYSTEM_TABLE *SystemTable +// Pointer to the EFI System Table. +// +// Output: +// VOID. +// +// Modified: +// pST +// pBS +// pRS +// TheImageHandle +// +// Referrals: +// +// Notes: +// The global variables initialized by this function are: +// pST Pointer to the EFI System Table. +// pBS Pointer to the Boot Services Table. +// pRS Pointer to the Runtime Services Table. +// TheImageHandle Image handle. +// +// +//************************************************************************* +VOID InitAmiLib( + IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable +) +{ + if (pST) return; + pST = SystemTable; + pBS = pST->BootServices; + pRS = pST->RuntimeServices; + TheImageHandle = ImageHandle; +} + +//************************************************************************* +// +// +// Name: GetEfiConfigurationTable +// +// Description: +// VOID *GetEfiConfigurationTable(IN EFI_SYSTEM_TABLE *SystemTable, +// IN EFI_GUID *Guid) retrieves a pointer to the system configuration table +// from the EFI System Table based on a specified GUID. If a match is found, +// then a pointer to the configuration table is returned. If a matching GUID +// is not found, then NULL is returned. +// +// Input: +// IN EFI_SYSTEM_TABLE *SystemTable +// Pointer to the EFI System Table. +// +// IN EFI_GUID *Guid +// Pointer to table's GUID type. +// +// Output: +// VOID* pointer to configuration table if a match is found; otherwise NULL. +// +// Modified: +// +// Referrals: +// guidcmp +// +// Notes: +// +// +//************************************************************************* +VOID * GetEfiConfigurationTable( + IN EFI_SYSTEM_TABLE *SystemTable, + IN EFI_GUID *Guid + ) +{ + EFI_CONFIGURATION_TABLE *Table = SystemTable->ConfigurationTable; + UINTN i = SystemTable->NumberOfTableEntries; + + for (;i;--i,++Table) + { + if (guidcmp(&Table->VendorGuid,Guid)==0) return Table->VendorTable; + } + return 0; +} + +#if EFI_SPECIFICATION_VERSION>=0x20000 +//************************************************************************* +// +// +// Name: LibInitStatusCodePtr +// +// Description: +// This function initializes pointers to StatusCode protocols in and outside SMM. +// +// Input: None +// +// Output: +// EFI_STATUS: EFI_SUCCESS - if pointer already initialized or LocateProtocol was successful. +// EFI_UNSUPPORTED - if no protocol was located. +// +// +//************************************************************************* +EFI_STATUS LibInitStatusCodePtr() +{ + EFI_STATUS Status = EFI_SUCCESS; +#if SMM_SUPPORT && !USE_DXE_STATUS_CODE_INSTANCE_IN_SMM + if (IsInSmm){ + if (!StatusCodeSmmPtr){ + if (IsAtRuntime) return EFI_UNSUPPORTED; + Status = pBS->LocateProtocol( + &gEfiSmmStatusCodeProtocolGuid,NULL,&StatusCodeSmmPtr + ); + } + return Status; + }else +#endif + if (!StatusCodePtr){ + if (IsAtRuntime) return EFI_UNSUPPORTED; + Status = pBS->LocateProtocol( + &gEfiStatusCodeRuntimeProtocolGuid,NULL,&StatusCodePtr + ); + } + return Status; +} + +//************************************************************************* +// +// +// Name: LibReportStatusCode +// +// Description: +// EFI_STATUS LibReportStatusCode(IN EFI_STATUS_CODE_TYPE Type, +// IN EFI_STATUS_CODE_VALUE Value, IN UINT32 Instance, +// IN EFI_GUID *CallerId OPTIONAL, IN EFI_STATUS_CODE_DATA *Data OPTIONAL) +// abstracts status code reporting. The Framework moved from a proprietary +// to a UEFI 2.0-based mechanism. This function abstracts the caller from +// how the status code is reported to prevent the code from having to change +// with this version of the specification supported. +// +// Input: +// IN EFI_STATUS_CODE_TYPE Type +// Indicates the type of status code being reported. +// +// IN EFI_STATUS_CODE_VALUE Value +// Describes the current status of a hardware or software entity. This +// includes information about the class and subclass that is used to classify +// the entity as well as an operation. For progress codes, the operation is +// the current activity. For error codes, it is the exception. For debug +// codes, it is not defined at this time. +// +// IN UINT32 Instance +// The enumeration of a hardware or software entity within the system. A +// system may contain multiple entities that match a class/subclass pairing. +// The instance differentiates between them. An instance of 0 indicates that +// instance information is unavailable, not meaningful, or not relevant. +// Valid instance numbers start with 1. +// +// IN EFI_GUID *CallerId OPTIONAL +// This optional parameter may be used to identify the caller. This parameter +// allows the status code driver to apply different rules to different +// callers. +// +// IN EFI_STATUS_CODE_DATA *Data OPTIONAL +// This optional parameter may be used to pass additional data. The contents +// of this data type may have additional GUID-specific data. +// +// Output: +// EFI_UNSUPPORTED, if Status Code protocol unavailable. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* + +EFI_STATUS LibReportStatusCode( + IN EFI_STATUS_CODE_TYPE Type, IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, IN EFI_GUID *CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL +){ + EFI_STATUS Status; +#if SMM_SUPPORT && !USE_DXE_STATUS_CODE_INSTANCE_IN_SMM + if (IsInSmm){ + if (StatusCodeSmmPtr==NULL) return EFI_NOT_FOUND; + return StatusCodeSmmPtr->ReportStatusCode(StatusCodeSmmPtr,Type,Value,Instance,CallerId,Data); + }else +#endif + Status = LibInitStatusCodePtr(); + if(EFI_ERROR(Status)) return Status; + return StatusCodePtr->ReportStatusCode(Type,Value,Instance,CallerId,Data); +} +#endif + +//************************************************************************* +// +// Name: PrintDebugMessageVaList +// +// Description: +// VOID PrintDebugMessageVaList(IN UINTN Level, IN CHAR8 *sFormat, +// IN va_list ArgList) generates a Status Code string with +// PrepareStatusCodeString, then outputs it through LibReportStatusCode. +// +// Input: +// IN UINTN Level +// The error level of the debug message. +// +// IN CHAR8 *sFormat +// Format string for the debug message to print. +// +// IN va_list ArgList +// Argument list for the format string. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// PrepareStatusCodeString +// LibReportStatusCode +// +// Notes: +// Helper function for Trace. +// +//************************************************************************* +VOID PrintDebugMessageVaList(UINTN Level, CHAR8 *sFormat, va_list ArgList) +{ + CHAR8 Buffer[2048]; + + PrepareStatusCodeString( Buffer, sizeof(Buffer), sFormat, ArgList ); + LibReportStatusCode( + EFI_DEBUG_CODE, + EFI_SOFTWARE_UNSPECIFIED, + 0, + NULL, + (EFI_STATUS_CODE_DATA*)Buffer + ); +} + +//************************************************************************* +// +// +// Name: Trace +// +// Description: +// VOID Trace(IN UINTN Level, IN CHAR8 *sFormat, IN ...) prints a debug +// message using status code protocol if the specified error level is +// enabled. +// +// Input: +// IN UINTN Level +// The error level of the debug message. +// +// IN CHAR8 *sFormat +// Format string for the debug message to print. +// +// IN ... +// Argument list for the format string. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// va_start +// PrintDebugMessageVaList +// va_end +// TRACE(Arguments) +// Sprintf +// +// Notes: +// Use the TRACE(Arguments) macro for generating debug messages in DXE. +// This allows the DEBUG_MODE token to control whether the debug message is +// included or removed in the build process. See Sprintf for format string +// parameters. +// +// +//************************************************************************* +VOID Trace(UINTN Level, CHAR8 *sFormat,...) +{ + extern const UINT32 TraceLevelMask; + va_list ArgList; + if ( ((UINT32)Level & TraceLevelMask) == 0 ) return; + ArgList = va_start(ArgList,sFormat); + PrintDebugMessageVaList(Level, sFormat, ArgList); + va_end(ArgList); +} + +//************************************************************************* +// +// +// Name: GetImageName +// +// Description: +// BOOLEAN GetImageName(IN EFI_HANDLE ImageHandle, OUT CHAR8 *sName) +// retrieves the name of the image specified by ImageHandle and returns it +// in sName. +// +// Input: +// IN EFI_HANDLE ImageHandle +// The image handle whose name is desired. +// +// OUT CHAR8 *sName +// Address of the null-terminated ASCII string to put image name into. User +// is reponsible for allocating the necessary memory resources. +// +// Output: +// TRUE if the image name has been found; otherwise, FALSE. +// +// Modified: +// +// Referrals: +// GetName +// Sprintf +// +// Notes: +// +// +//************************************************************************* +BOOLEAN GetImageName(EFI_HANDLE ImageHandle, CHAR8 *sName) +{ + EFI_LOADED_IMAGE_PROTOCOL *pImage; + EFI_COMPONENT_NAME_PROTOCOL *pComponentName; + CHAR16 *wsName; + EFI_STATUS Status; + if ( !EFI_ERROR(Status = pBS->HandleProtocol(ImageHandle,&gEfiLoadedImageProtocolGuid,&pImage)) + && GetName((UINT8*)pImage->ImageBase,sName) + ) return TRUE; + + if ( !EFI_ERROR(pBS->HandleProtocol(ImageHandle,&gEfiComponentName2ProtocolGuid,&pComponentName)) + && !EFI_ERROR(pComponentName->GetDriverName(pComponentName,LANGUAGE_CODE_ENGLISH,&wsName)) +#if EFI_SPECIFICATION_VERSION > 0x20000 +//Try UEFI 2.0 ComponentName protocol + || !EFI_ERROR(pBS->HandleProtocol(ImageHandle,&gEfiComponentNameProtocolGuid,&pComponentName)) + && !EFI_ERROR(pComponentName->GetDriverName(pComponentName,"eng",&wsName)) +#endif + ) + { + Sprintf(sName,"%S", wsName); + return TRUE; + } + if ( !EFI_ERROR(Status) + && pImage->FilePath->Type==MEDIA_DEVICE_PATH + && pImage->FilePath->SubType==MEDIA_FV_FILEPATH_DP + ) + { + Sprintf(sName,"[%G]",&((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH*)pImage->FilePath)->NameGuid); + return TRUE; + } + Sprintf(sName,"Unknown"); + return FALSE; +} + +//************************************************************************* +// +// +// Name: FindDeviceName +// +// Description: +// BOOLEAN FindDeviceName( IN EFI_HANDLE Controller, IN EFI_HANDLE Child, +// OUT CHAR16 **wsName) checks all the protocols associated with a device +// handle and its child controller for its name; if a child is not defined, +// checks all associated protocols. +// +// Input: +// IN EFI_HANDLE Controller +// The image handle whose name is desired. +// +// IN EFI_HANDLE Child +// The child handle to be checked. If set to NULL, checks all protocols +// associated with the Controller instead. +// +// OUT CHAR16 **wsName +// Address of the null-terminated Unicode string to put device name into. +// User is reponsible for allocating the necessary memory resources. +// +// Output: +// TRUE if device name found; otherwise, FALSE. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +BOOLEAN FindDeviceName( + EFI_HANDLE Controller, EFI_HANDLE Child, + CHAR16 **wsName, BOOLEAN *ChildFound +){ + UINTN i, Count; + EFI_GUID **ppGuid; + BOOLEAN NameFound = FALSE; + UINT32 Attributes = Child ? EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER : EFI_OPEN_PROTOCOL_BY_DRIVER; + if (EFI_ERROR(pBS->ProtocolsPerHandle(Controller, &ppGuid, &Count))) return FALSE; + if (ChildFound) *ChildFound=FALSE; + for(i=0; !NameFound && iOpenProtocolInformation( + Controller,ppGuid[i],&pInfo,&InfoCount + ))) continue; + for(j=0; jHandleProtocol( + pInfo[j].AgentHandle,&gEfiComponentName2ProtocolGuid,&pComponentName + ))){ + if (!EFI_ERROR(pComponentName->GetControllerName( + pComponentName,Controller,Child,LANGUAGE_CODE_ENGLISH,wsName + ))){NameFound=TRUE; break;} + } +#if EFI_SPECIFICATION_VERSION > 0x20000 +//Try UEFI 2.0 ComponentName protocol + if (!EFI_ERROR(pBS->HandleProtocol( + pInfo[j].AgentHandle,&gEfiComponentNameProtocolGuid,&pComponentName + ))){ + if (!EFI_ERROR(pComponentName->GetControllerName( + pComponentName,Controller,Child,"eng",wsName + ))){NameFound=TRUE; break;} + } +#endif + } + if (InfoCount) pBS->FreePool(pInfo); + } + if (Count) pBS->FreePool(ppGuid); + return NameFound; +} + +//************************************************************************* +// +// +// Name: GetControllerName +// +// Description: +// BOOLEAN GetControllerName(IN EFI_HANDLE Controller, OUT CHAR16 **wsName) +// retrieves the name of the controller specified by Controller and copies +// it into the caller allocated Unicode string at address wsName. +// +// Input: +// IN EFI_HANDLE Controller +// Handle of the controller whose name is desired. +// +// OUT CHAR16 **wsName +// Address of the null-terminated Unicode string to put controller name into. +// +// Output: +// TRUE if name found; otherwise, FALSE. +// +// Modified: +// +// Referrals: +// FindDeviceName +// DPCopy +// DPGetLastNode +// +// Notes: +// +// +//************************************************************************* +BOOLEAN GetControllerName(EFI_HANDLE Controller, CHAR16 **wsName) +{ + const EFI_DEVICE_PATH_PROTOCOL End = {END_DEVICE_PATH,END_ENTIRE_SUBTYPE,sizeof(EFI_DEVICE_PATH_PROTOCOL)}; + BOOLEAN NameFound; + EFI_HANDLE Parent; + EFI_DEVICE_PATH_PROTOCOL *pDevicePath, *pLastNode, *pDp; + BOOLEAN ChildFound; + + if (FindDeviceName(Controller, NULL, wsName, NULL)) return TRUE; + if (EFI_ERROR(pBS->HandleProtocol(Controller, &guidDevicePath, &pDevicePath))) return FALSE; + pDevicePath = DPCopy(pDevicePath); + do{ + ChildFound=TRUE; + pDp = pDevicePath; + pLastNode = DPGetLastNode(pDevicePath); + if (!pLastNode){ + NameFound = FALSE; + break; + } + *pLastNode = End; + if ( !EFI_ERROR(pBS->LocateDevicePath(&guidDevicePath, &pDp, &Parent)) + && pDp==pLastNode + ){ + NameFound = FindDeviceName(Parent, Controller, wsName, &ChildFound); + }else{ + NameFound = FALSE; + break; + } + }while(!ChildFound); + pBS->FreePool(pDevicePath); + return NameFound; +} + +//************************************************************************* +// +// +// Name: FvReadPe32Image +// +// Description: +// EFI_STATUS FvReadPe32Image(IN EFI_GUID *NameGuid, IN OUT VOID **Buffer, +// IN OUT UINTN *BufferSize, OUT UINT32 *AuthenticationStatus) +// +// Input: +// IN EFI_GUID *NameGuid +// GUID associated with the image in the firmware volume. +// +// IN OUT VOID **Buffer +// Pointer to buffer for the image to be returned in. Caller may specify +// *Buffer = NULL, in which case FvReadPe32Image will dynamically allocate +// the necessary amount of memory and return the pointer to the buffer +// here. +// +// IN OUT UINTN *BufferSize +// If Buffer is caller allocated, caller must put size of the Buffer here. +// Returns with the size of the image, even in the case the caller allocated +// Buffer is too small. +// +// OUT UINT32 *AuthenticationStatus) +// Pointer to a caller-allocated UINT32 in which the authentication status +// is returned. See Possible AuthenticationStatus Bit Values in the EFI +// Firmware Volume Specification for more information. +// +// Output: +// EFI_WARN_BUFFER_TOO_SMALL, if Buffer is too small to contain image. +// BufferSize is updated with the necessary size, +// and Buffer is filled with the truncated image. +// EFI_OUT_OF_RESOURCES, if an allocation failure occurred. +// EFI_NOT_FOUND, if the requested file or EFI_SECTION_PE32 was +// not found. +// EFI_DEVICE_ERROR, if a hardware error occurred when attempting +// to access the firmware volume. +// EFI_ACCESS_DENIED, if the firmware volume is configured to +// disallow reads. +// EFI_PROTOCOL_ERROR, if the GUIDED_SECTION_EXTRACTION_PROTOCOL for +// the EFI_SECTION_PE32 was not found. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// guidFV +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS FvReadPe32Image ( + IN EFI_GUID *NameGuid, + IN OUT VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT UINT32 *AuthenticationStatus) +{ + EFI_FIRMWARE_VOLUME_PROTOCOL *Fv; + + EFI_STATUS Status; + UINTN NumHandles; + EFI_HANDLE *HandleBuffer; + UINTN i; + + Status = pBS->LocateHandleBuffer(ByProtocol,&guidFV,NULL,&NumHandles,&HandleBuffer); + if (EFI_ERROR(Status)) return Status; + + for (i = 0; i< NumHandles; ++i) + { + pBS->HandleProtocol(HandleBuffer[i],&guidFV,&Fv); + Status = Fv->ReadSection( + Fv,NameGuid, + EFI_SECTION_PE32,0, + Buffer,BufferSize, + AuthenticationStatus + ); + if (!EFI_ERROR(Status)) break; + } + + pBS->FreePool(HandleBuffer); + return Status; +} + +//************************************************************************* +// +// +// Name: Malloc +// +// Description: +// VOID *Malloc(IN UINTN Size) allocates Size bytes of memory from +// EfiBootServicesData and returns a pointer to the allocated space. +// +// Input: +// IN UINTN Size +// The number of bytes to be allocated. +// +// Output: +// VOID* address of the allocated memory. +// +// Modified: +// +// Referrals: +// +// Notes: +// This function is available only in the DXE phase. Use +// pBS->FreePool(VOID*) to return memory to the pool once it's no longer +// needed. +// +// +//************************************************************************* +void* Malloc(UINTN Size){ + VOID *p=NULL; + pBS->AllocatePool(EfiBootServicesData,Size,&p); + return p; +} + +//************************************************************************* +// +// +// Name: MallocZ +// +// Description: +// VOID* MallocZ(IN UINTN Size) allocates Size bytes of memory from +// EfiBootServicesData, initializes it to zero, then returns a pointer to +// the allocated space. +// +// Input: +// IN UINTN Size +// The number of bytes to be allocated. +// +// Output: +// VOID* address of the allocated and zeroed memory. +// +// Modified: +// +// Referrals: +// Malloc +// +// Notes: +// +// +//************************************************************************* +void* MallocZ(UINTN Size){ + VOID *p=NULL; + p=Malloc(Size); + if(!p) return p; + pBS->SetMem(p,Size,0); + return p; +} + +static UINT8 DevicePathTypes[] = { + HARDWARE_DEVICE_PATH, + ACPI_DEVICE_PATH, + MESSAGING_DEVICE_PATH, + MEDIA_DEVICE_PATH, + BBS_DEVICE_PATH, + END_DEVICE_PATH, + END_DEVICE_PATH1 +}; + +static UINTN DevicePathTypesSize = sizeof(DevicePathTypes) / sizeof(UINT8); +#define MAX_DP_SIZE 0x10000 + +EFI_STATUS IsValidDevicePath( + IN EFI_DEVICE_PATH_PROTOCOL *pDp +) +{ + UINTN i; + UINTN DevicePathSize = 0; + + for( ; !(isEndNode(pDp) && pDp->SubType == END_ENTIRE_SUBTYPE); pDp = NEXT_NODE(pDp) ) { + UINTN NodeLength = NODE_LENGTH(pDp); + if (NodeLength < sizeof(EFI_DEVICE_PATH_PROTOCOL)) return EFI_INVALID_PARAMETER; + DevicePathSize += NodeLength; + for(i = 0; i < DevicePathTypesSize; i++) { + if(pDp->Type == DevicePathTypes[i]) + break; + } + if((i == DevicePathTypesSize) || (DevicePathSize > MAX_DP_SIZE)) //unknown device path type or big size + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; +} + +//************************************************************************* +// +// +// Name: DPLength +// +// Description: +// UINTN DPLength(IN EFI_DEVICE_PATH_PROTOCOL *pDp) returns the length of +// the provided device path, pDp (including the size of EndOfDevicePath). +// +// Input: +// IN EFI_DEVICE_PATH_PROTOCOL *pDp +// The device path whose length is desired. +// +// Output: +// UINTN size of the device path, pDp, including EndOfDevicePath. +// +// Modified: +// +// Referrals: +// isEndNode +// NEXT_NODE +// NODE_LENGTH +// +// Notes: +// +// +//************************************************************************* +UINTN DPLength(EFI_DEVICE_PATH_PROTOCOL *pDp) +{ + UINTN Size; + if (!pDp) return 0; + Size = 0; + for( + ; !(isEndNode(pDp) && pDp->SubType==END_ENTIRE_SUBTYPE) + ; pDp = NEXT_NODE(pDp) + ){ + UINTN Length = NODE_LENGTH(pDp); + //Protection from the junk data. + //Zero type and zero length are illegal. + //If we encountered them, return + if (!pDp->Type || !Length) return Size; + Size += Length; + } + return Size + sizeof(EFI_DEVICE_PATH_PROTOCOL); // add size of END_DEVICE_PATH node +} + +static EFI_DEVICE_PATH_PROTOCOL EndOfDevicePathNode = { + END_DEVICE_PATH, END_ENTIRE_SUBTYPE, + {sizeof(EFI_DEVICE_PATH_PROTOCOL),0} +}; + +//************************************************************************* +// +// +// Name: DPAddNode +// +// Description: +// VOID* DPAddNode(IN EFI_DEVICE_PATH_PROTOCOL *pDp1, +// IN EFI_DEVICE_PATH_PROTOCOL *pDp2) adds the very first element of pDp2 to +// pDp1 just before its device path terminator, and returns the result in a +// newly allocated buffer. +// +// Input: +// IN EFI_DEVICE_PATH_PROTOCOL *pDp1 +// The device path to be appended to. Element will be inserted prior to +// pDp1's device path terminator. Device path will not be altered. +// +// IN EFI_DEVICE_PATH_PROTOCOL *pDp2 +// The device path to be read from. The very first element will be appended +// to pDp1; note that pDp2 does not require a device path terminator. +// +// Output: +// VOID* address of the modified device path. User is responsible for +// managing this piece of memory. +// +// Modified: +// +// Referrals: +// DPCopy +// DPLength +// Malloc +// MemCpy +// NODE_LENGTH +// +// Notes: +// +// +//************************************************************************* +VOID* DPAddNode(EFI_DEVICE_PATH_PROTOCOL *pDp1, EFI_DEVICE_PATH_PROTOCOL *pDp2) +{ + UINTN l1; + UINT8 *NewDp, *p; + + if (!pDp2) return (pDp1) ? DPCopy(pDp1) : DPCopy(&EndOfDevicePathNode); + + l1 = pDp1 ? DPLength(pDp1)-sizeof(EFI_DEVICE_PATH_PROTOCOL) : 0; + NewDp = Malloc(l1+NODE_LENGTH(pDp2)+sizeof(EFI_DEVICE_PATH_PROTOCOL)); + p = NewDp; + + if (l1) { MemCpy(p, pDp1, l1); p+=l1; } + MemCpy(p, pDp2, NODE_LENGTH(pDp2)); p+=NODE_LENGTH(pDp2); + *((EFI_DEVICE_PATH_PROTOCOL*)p) = EndOfDevicePathNode; + return NewDp; +} + +//************************************************************************* +// +// +// Name: DPAdd +// +// Description: +// VOID* DPAdd(IN EFI_DEVICE_PATH_PROTOCOL *pDp1, +// IN EFI_DEVICE_PATH_PROTOCOL *pDp2) appends all the elements of pDp2 just +// before the device path terminator of pDp1, and returns the result in a +// newly allocated buffer. +// +// Input: +// IN EFI_DEVICE_PATH_PROTOCOL *pDp1 +// The device path to be appended to. Element(s) will be inserted prior to +// pDp1's device path terminator. Device path will not be altered. +// +// IN EFI_DEVICE_PATH_PROTOCOL *pDp2 +// The device path to be read from. All elements will be appended to pDp1. +// If NULL, returns copy of pDp1. +// +// Output: +// VOID* address of the modified device path. User is responsible for +// managing this piece of memory. +// +// Modified: +// +// Referrals: +// DPCopy +// DPLength +// Malloc +// MemCpy +// +// Notes: +// +// +//************************************************************************* +VOID* DPAdd(EFI_DEVICE_PATH_PROTOCOL *pDp1, EFI_DEVICE_PATH_PROTOCOL *pDp2) +{ + UINTN l1,l2; + UINT8 *NewDp,*p; + + if (!pDp1) return (pDp2) ? DPCopy(pDp2) : DPCopy(&EndOfDevicePathNode); + if (!pDp2) return DPCopy(pDp1); + + l1 = DPLength(pDp1)-sizeof(EFI_DEVICE_PATH_PROTOCOL); + l2 = DPLength(pDp2); + NewDp = Malloc(l1+l2); + p = NewDp; + + MemCpy(p, pDp1, l1); p+=l1; + MemCpy(p, pDp2, l2); + return NewDp; +} + +//************************************************************************* +// +// +// Name: DPAddInstance +// +// Description: +// VOID* DPAddInstance(IN EFI_DEVICE_PATH_PROTOCOL *pDp1, +// IN EFI_DEVICE_PATH_PROTOCOL *pDp2) makes a new device path with pDp1 as +// its first instance and pDp2 as its second instance, then returns the +// result in a newly allocated buffer. +// +// Input: +// IN EFI_DEVICE_PATH_PROTOCOL *pDp1 +// The first device path instance. +// +// IN EFI_DEVICE_PATH_PROTOCOL *pDp2 +// The second device path instance. +// +// Output: +// VOID* address of the modified device path. User is responsible for +// managing this piece of memory. +// +// Modified: +// +// Referrals: +// DPCopy +// DPLength +// Malloc +// MemCpy +// +// Notes: +// +// +//************************************************************************* +VOID* DPAddInstance(EFI_DEVICE_PATH_PROTOCOL *pDp1, EFI_DEVICE_PATH_PROTOCOL *pDp2) +{ + UINTN l1,l2; + UINT8 *NewDp,*p; + + if (!pDp2) return NULL; + if (!pDp1) return DPCopy(pDp2); + //Uncomment if pDp2 can be NULL:if (!pDp2) return DPCopy(pDp1); + + l1 = DPLength(pDp1); + l2 = DPLength(pDp2); + NewDp = Malloc(l1+l2); + p = NewDp; + + MemCpy(p, pDp1, l1); p+=l1; + (((EFI_DEVICE_PATH_PROTOCOL*)p)-1)->SubType = END_INSTANCE_SUBTYPE; + MemCpy(p, pDp2, l2); + return NewDp; +} + +//************************************************************************* +// +// +// Name: DPCopy +// +// Description: +// VOID* DPCopy(IN EFI_DEVICE_PATH_PROTOCOL *pDp) copies the user provided +// device path into a new buffer and returns its address. +// +// Input: +// IN EFI_DEVICE_PATH_PROTOCOL *pDp +// The device path to be copied. +// +// Output: +// VOID* address of the new copy of pDp. User is responsible for managing +// this piece of memory. +// +// Modified: +// +// Referrals: +// DPLength +// Malloc +// MemCpy +// +// Notes: +// +// +//************************************************************************* +VOID* DPCopy(EFI_DEVICE_PATH_PROTOCOL *pDp) +{ + UINTN l; + UINT8 *p; + + if (!pDp) return NULL; + l = DPLength(pDp); + p = Malloc(l); + MemCpy(p, pDp, l); + return p; +} + +//************************************************************************* +// +// +// Name: DPIsOneOf +// +// Description: +// BOOLEAN DPIsOneOf(IN EFI_DEVICE_PATH_PROTOCOL *pAll, +// IN EFI_DEVICE_PATH_PROTOCOL *pOne, IN BOOLEAN ExactMatch) determines +// whether a device path, pAll, contains another device path, pOne. If the +// ExactMatch parameter is TRUE, it checks for an exact match instead. +// +// +// Input: +// IN EFI_DEVICE_PATH_PROTOCOL *pAll +// The device path to be scanned. +// +// IN EFI_DEVICE_PATH_PROTOCOL *pOne +// The device path to locate within pAll. +// +// IN BOOLEAN ExactMatch +// If TRUE, checks whether pAll is exactly pOne. +// +// Output: +// TRUE if pAll contains pOne and ExactMatch is FALSE, or if pAll equals +// pOne and ExactMatch is TRUE. Otherwise, FALSE. +// +// Modified: +// +// Referrals: +// NODE_LENGTH +// isEndNode +// MemCmp +// NEXT_NODE +// +// Notes: +// +// +//************************************************************************* +BOOLEAN DPIsOneOf(EFI_DEVICE_PATH_PROTOCOL *pAll, EFI_DEVICE_PATH_PROTOCOL *pOne, BOOLEAN ExactMatch) +{ + do{ + EFI_DEVICE_PATH_PROTOCOL *pPath; + for( pPath = pOne + ; NODE_LENGTH(pPath)==NODE_LENGTH(pAll) + && !isEndNode(pPath) + && !MemCmp(pPath, pAll, NODE_LENGTH(pAll)) + ; pPath=NEXT_NODE(pPath), pAll=NEXT_NODE(pAll) + ) ; + if (isEndNode(pAll) && (!ExactMatch || isEndNode(pPath))) return TRUE; + for(; !isEndNode(pAll); pAll = NEXT_NODE(pAll)) ; + if (pAll->SubType==END_ENTIRE_SUBTYPE) return FALSE; + pAll++ ; + }while (TRUE); +} + +//************************************************************************* +// +// +// Name: DPGetLastNode +// +// Description: +// VOID* DPGetLastNode(IN EFI_DEVICE_PATH_PROTOCOL *pDp) returns a pointer +// to the very last device path node before END_OF_DEVICE_PATH node. +// +// Input: +// IN EFI_DEVICE_PATH_PROTOCOL *pDp +// The device path whose last node is needed. +// +// Output: +// VOID* address of the last device path node before END_OF_DEVICE_PATH in +// the provided device path, pDp. +// +// Modified: +// +// Referrals: +// isEndNode +// NEXT_NODE +// +// Notes: +// +// +//************************************************************************* +VOID* DPGetLastNode(EFI_DEVICE_PATH_PROTOCOL *pDp) +{ + EFI_DEVICE_PATH_PROTOCOL *dp=NULL; +//--------------------------------- + if(!pDp)return dp; + for( ; !isEndNode(pDp); pDp=NEXT_NODE(pDp)) dp = pDp; + return dp; +} + +//************************************************************************* +// +// +// Name: DPCmp +// +// Description: +// INTN DPCmp(IN EFI_DEVICE_PATH_PROTOCOL *pDp1, +// IN EFI_DEVICE_PATH_PROTOCOL *pDp2) compares two device paths, pDp1 and +// pDp2, and returns zero if both are equivalent; otherwise, it returns +// a non-zero value. +// +// Input: +// IN EFI_DEVICE_PATH_PROTOCOL *pDp1 +// Address of the first device path to compare. +// +// IN EFI_DEVICE_PATH_PROTOCOL *pDp2 +// Address of the second device path to compare. +// +// Output: +// INTN non-zero value if both input device paths are not equivalent; +// otherwise, zero. +// +// Modified: +// +// Referrals: +// DPLength +// MemCmp +// +// Notes: +// +// +//************************************************************************* +//Compares Dp1 and Dp2 returns ZERO if Dp1==Dp2, NONZERO if Dp1!=Dp2 +INTN DPCmp(EFI_DEVICE_PATH_PROTOCOL *pDp1, EFI_DEVICE_PATH_PROTOCOL *pDp2){ + UINTN len; +//--------------------- + if(!pDp1 && !pDp2) return 0; //if both is NULL than Dp1==Dp2 + if(!pDp1 || !pDp2) return -1; // if one is NULL than Dp1!=Dp2 + len=DPLength(pDp1); + if(DPLength(pDp2)!=len) return -1; + return MemCmp(pDp1,pDp2, len); +} + +//************************************************************************* +// +// +// Name: DPCut +// +// Description: +// VOID* DPCut(IN EFI_DEVICE_PATH_PROTOCOL *pDp) creates a new device path +// containing all but the last node of pDp, then returns the address to the +// new device path. +// +// Input: +// IN EFI_DEVICE_PATH_PROTOCOL *pDp +// The device path to be copied. +// +// Output: +// VOID* address of the new copy of pDp containing all but the last node. +// Returns NULL if there is not enough memory or pDp is NULL. +// +// Modified: +// +// Referrals: +// DPGetLastNode +// Malloc +// MemCpy +// SET_NODE_LENGTH +// +// Notes: +// +// +//************************************************************************* +VOID *DPCut(EFI_DEVICE_PATH_PROTOCOL *pDp) +{ + EFI_DEVICE_PATH_PROTOCOL *pdp, *edp; + UINTN len; +//------------------------------ + if(!pDp)return NULL; + pdp=DPGetLastNode(pDp); + len=(UINTN)pdp-(UINTN)pDp; + if(len==0) return NULL; + pdp=Malloc(len+sizeof(EFI_DEVICE_PATH_PROTOCOL)); + ASSERT(pdp) + MemCpy(pdp,pDp,len); + edp=(EFI_DEVICE_PATH_PROTOCOL*)((UINT8*)pdp+len); + edp->Type=END_DEVICE_PATH; + edp->SubType=END_ENTIRE_SUBTYPE; + SET_NODE_LENGTH(edp,END_DEVICE_PATH_LENGTH); + return pdp; +} + +//************************************************************************* +// +// +// Name: DPGetEndNode +// +// Description: +// EFI_DEVICE_PATH_PROTOCOL* DPGetEndNode(IN EFI_DEVICE_PATH_PROTOCOL *pDp) +// returns the end of the device path node for the specified device path. +// +// Input: +// IN EFI_DEVICE_PATH_PROTOCOL *pDp +// Address of the device path. +// +// Output: +// EFI_DEVICE_PATH_PROTOCOL* address of the end of device path node. NULL +// if pDp is NULL. +// +// Modified: +// +// Referrals: +// isEndNode +// NEXT_NODE +// +// Notes: +// +// +//************************************************************************* +EFI_DEVICE_PATH_PROTOCOL* DPGetEndNode(EFI_DEVICE_PATH_PROTOCOL *pDp) +{ + if(!pDp)return NULL; + for( ; !isEndNode(pDp); pDp=NEXT_NODE(pDp)) ; + return pDp; +} + +//************************************************************************* +// +// +// Name: DPNextInstance +// +// Description: +// VOID* DPNextInstance(IN OUT EFI_DEVICE_PATH_PROTOCOL **ppDp, +// OUT UINTN *pSize) creates a copy of the current device path instance. It +// also updates DevicePath to point to the next device path instance in the +// device path (or NULL if no more) and updates Size to hold the size of the +// device path instance copy. If DevicePath is NULL, then NULL is returned. +// If there is not enough memory to allocate space for the new device path, +// then NULL is returned. The memory is allocated from EFI boot services +// memory. It is the responsibility of the caller to free the memory +// allocated. +// +// Input: +// IN OUT EFI_DEVICE_PATH_PROTOCOL **ppDp +// On input, this holds the pointer to the current device path instance. On +// output, this holds the pointer to the next device path instance or NULL +// if there are no more device path instances in the device path pointer to +// a device path data structure. +// +// OUT UINTN *pSize +// On output, this holds the size of the device path instance, in bytes, or +// zero if DevicePath is NULL. +// +// Output: +// VOID* address of a copy of the next device path instance. NULL if there +// are no more device path instances, or not enough memory, or the provided +// device path was NULL. It is the responsibility of the caller to free the +// memory allocated. +// +// Modified: +// +// Referrals: +// DPGetEndNode +// Malloc +// MemCpy +// +// Notes: +// +// +//************************************************************************* +VOID* DPNextInstance(EFI_DEVICE_PATH_PROTOCOL **ppDp, UINTN *pSize) +{ + EFI_DEVICE_PATH_PROTOCOL *pEnd, *pNew; + UINTN Size; + if (pSize) *pSize=0; + if (!ppDp) return NULL; + pEnd = DPGetEndNode(*ppDp); + if (!pEnd) return NULL; + Size = (UINT8*)(pEnd+1) - (UINT8*)*ppDp; + if (pSize) *pSize=Size; + if (!(pNew = Malloc(Size))) return NULL; + MemCpy(pNew,*ppDp, Size); + ((EFI_DEVICE_PATH_PROTOCOL*)((UINT8*)pNew+Size)-1)->SubType = END_ENTIRE_SUBTYPE; + if (pEnd->SubType==END_ENTIRE_SUBTYPE) *ppDp = NULL; + else *ppDp = pEnd+1; + return pNew; +} + +//************************************************************************* +// +// +// Name: DPCreateNode +// +// Description: +// VOID* DPCreateNode(IN UINT8 Type, IN UINT8 SubType, IN UINT16 Length) +// creates a new device node in a newly allocated buffer of size NodeLength +// and initializes the device path node header with NodeType and NodeSubType. +// The new device path node is returned. If NodeLength is smaller than a +// device path header, then NULL is returned. If there is not enough memory +// to allocate space for the new device path, then NULL is returned. The +// memory is allocated from EFI boot services memory. It is the +// responsibility of the caller to free the memory allocated. +// +// Input: +// IN UINT8 Type +// The device node type for the new device node. +// +// IN UINT8 SubType +// The device node sub-type for the new device node. +// +// IN UINT16 Length +// The length of the new device node. +// +// Output: +// VOID* address of the new device path node. NULL if NodeLength is +// smaller than a device path header, or there is not enough memory. +// +// Modified: +// +// Referrals: +// Malloc +// SET_NODE_LENGTH +// +// Notes: +// +// +//************************************************************************* +VOID* DPCreateNode(UINT8 Type, UINT8 SubType, UINT16 Length) +{ + EFI_DEVICE_PATH_PROTOCOL *pDp; + + if (LengthType = Type; + pDp->SubType = SubType; + SET_NODE_LENGTH(pDp,Length); + return pDp; +} + +//************************************************************************* +// +// +// Name: DPIsMultiInstance +// +// Description: +// BOOLEAN DPIsMultiInstance(IN EFI_DEVICE_PATH_PROTOCOL* pDp) determines +// if a device path is single or multi-instance. This function returns TRUE +// if the device path specified by pDp is multi-instance. Otherwise, FALSE +// is returned. If pDp is NULL, then FALSE is returned. +// +// Input: +// IN EFI_DEVICE_PATH_PROTOCOL* pDp +// A pointer to a device path data structure. +// +// Output: +// TRUE if the device path specified by DevicePath is multi-instance. +// FALSE if pDp is NULL or not multi-instance. +// +// Modified: +// +// Referrals: +// DPGetEndNode +// +// Notes: +// +// +//************************************************************************* +BOOLEAN DPIsMultiInstance(EFI_DEVICE_PATH_PROTOCOL* pDp) +{ + if (!pDp) return FALSE; + return DPGetEndNode(pDp)->SubType != END_ENTIRE_SUBTYPE; +} + +//************************************************************************* +// +// +// Name: TimerIsSet +// +// Description: +// VOID TimerIsSet(IN EFI_EVENT Event, IN OUT VOID *Context) +// +// Input: +// +// Output: +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +VOID TimerIsSet(EFI_EVENT Event, VOID *Context) +{ + *(BOOLEAN*)Context = TRUE; +} + +//************************************************************************* +// +// +// Name: TimerStart +// +// Description: +// EFI_EVENT TimerStart(OUT BOOLEAN *pTimerFlag, IN UINT64 Delay) +// +// Input: +// +// Output: +// +// Modified: +// +// Referrals: +// TimerIsSet +// +// Notes: +// +// +//************************************************************************* +EFI_EVENT TimerStart(BOOLEAN *pTimerFlag, UINT64 Delay) +{ + EFI_STATUS Status; + EFI_EVENT Event; + + *pTimerFlag = FALSE; + + Status = pBS->CreateEvent( + EVT_TIMER|EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + TimerIsSet, + pTimerFlag, + &Event + ); + if (EFI_ERROR(Status)) return NULL; + + + Status = pBS->SetTimer(Event, TimerRelative, Delay); + if (EFI_ERROR(Status)) + { + pBS->CloseEvent(Event); + return NULL; + } + + return Event; +} + +//************************************************************************* +// +// +// Name: TimerStop +// +// Description: +// VOID TimerStop(IN BOOLEAN TimerFlag, IN EFI_EVENT Event) +// +// Input: +// +// Output: +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +void TimerStop(BOOLEAN TimerFlag, EFI_EVENT Event) +{ + if (!TimerFlag) pBS->SetTimer(Event, TimerCancel,0); + pBS->CloseEvent(Event); +} + +//************************************************************************* +// +// +// Name: FSReadFile +// +// Description: +// EFI_STATUS FSReadFile(IN EFI_HANDLE hDevice, IN EFI_DEVICE_PATH_PROTOCOL* pPath, OUT VOID** ppSource, OUT UINTN *pSize) +// +// Input: +// +// Output: +// +// Modified: +// +// Referrals: +// isEndNode +// NODE_LENGTH +// MemCpy +// Malloc +// NEXT_NODE +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS FSReadFile(EFI_HANDLE hDevice, EFI_DEVICE_PATH_PROTOCOL* pPath, VOID** ppSource, UINTN *pSize) +{ + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pFS; + EFI_FILE_PROTOCOL *pRootFile=NULL, *pFile=NULL; +//S.Y. +//FileInfo contains not a pointer to FileName Buffer +//But Copy of the file name at the very end of the file + EFI_FILE_INFO *pFileInfo=NULL; +//S.Y. + UINTN Size=0; + CHAR16 *wsFileName; + EFI_DEVICE_PATH_PROTOCOL *pDp; + VOID *pSource = NULL; + EFI_STATUS Status; + if (EFI_ERROR(pBS->HandleProtocol(hDevice, &guidFS, &pFS))) return EFI_NOT_FOUND; + if (EFI_ERROR(pFS->OpenVolume(pFS,&pRootFile))) return EFI_NOT_FOUND; + //create file name + //1. Determine Buffer size to hold filename + Size = 0; + pDp = pPath; + while(!isEndNode(pDp)){ + if(pDp->Type == MEDIA_DEVICE_PATH && pDp->SubType == MEDIA_FILEPATH_DP){ + Size=Size+(NODE_LENGTH(pDp)-sizeof(EFI_DEVICE_PATH_PROTOCOL)); + } else break; + pDp = NEXT_NODE(pDp); + } + + if ( !isEndNode(pDp) ) return EFI_NOT_FOUND; + //2. Alocate buffer for file name + wsFileName = Malloc(Size); + if (!wsFileName) return EFI_OUT_OF_RESOURCES; + //3.Copy Characters fron FileDevicePAth to the Buffer + Size=0;//Now Size will show position of char in wsFileName buffer + pDp = pPath; + while(!isEndNode(pDp)){ + if(pDp->Type == MEDIA_DEVICE_PATH && pDp->SubType == MEDIA_FILEPATH_DP){ + UINTN l = NODE_LENGTH(pDp)-sizeof(EFI_DEVICE_PATH_PROTOCOL); + MemCpy(wsFileName+Size,pDp+1,l); + Size=Size+(l/sizeof(CHAR16)); +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO +//EFI Shell prepares File DevicePath very strange it should not be like this +//when you calling App from fsX:\DIR_NAME> app_name it creates following dev path entry +//(\DIR_NAME);('.');(APP_NAME.efi);(END_DP). +//but when you type fsX:\> DIR_NAME\app_name it creates +// (\);(DIR_NAME\);(app_name);(END_DP). + //repleace str_terminator with "\" char if previouse char is not "\" + if(wsFileName[Size-2]!=0x005c) wsFileName[Size-1]=0x005c; //"\"symbol + else Size--; +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO + } else break; + pDp = NEXT_NODE(pDp); + } + + wsFileName[Size-1]=0; + Status = pRootFile->Open(pRootFile,&pFile,wsFileName,EFI_FILE_MODE_READ,0); + pBS->FreePool(wsFileName); + if (EFI_ERROR(Status)) return EFI_NOT_FOUND; +//S.Y. + //Size = sizeof(FileInfo); + Size=0; + //Try to determine Size of memory to allocate for EFI_FILE_INFO var + Status=pFile->GetInfo(pFile,&guidFileInfo,&Size,pFileInfo); +// if (!EFI_ERROR(Status=pFile->GetInfo(pFile,&guidFileInfo,&Size,&FileInfo))) + if(EFI_ERROR(Status)){ + if (Status==EFI_BUFFER_TOO_SMALL){ + pFileInfo=Malloc(Size); + if(!pFileInfo) { + Status=EFI_OUT_OF_RESOURCES; + goto Done; + } + } else goto Done; + } + + Status=pFile->GetInfo(pFile,&guidFileInfo,&Size,pFileInfo); + if(EFI_ERROR(Status)){ + pBS->FreePool(pFileInfo); + goto Done; + } + + Size = (UINTN)pFileInfo->FileSize; + + pBS->FreePool(pFileInfo); + + pSource=Malloc(Size); + if (!pSource) Status=EFI_OUT_OF_RESOURCES; + else Status=pFile->Read(pFile,&Size,pSource); + +Done: + if(pFile)pFile->Close(pFile); + if(pRootFile)pRootFile->Close(pRootFile); + if (EFI_ERROR(Status) && pSource){ + pBS->FreePool(pSource); + return Status; + } + *ppSource = pSource; + *pSize = Size; + return EFI_SUCCESS; +} + +//************************************************************************* +// +// +// Name: FVReadFile +// +// Description: +// EFI_STATUS FVReadFile(IN EFI_HANDLE hDevice, IN EFI_GUID* pFileName, OUT VOID** ppSource, OUT UINTN *pSize) +// +// Input: +// +// Output: +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS FVReadFile(EFI_HANDLE hDevice, EFI_GUID* pFileName, VOID** ppSource, UINTN *pSize) +{ + EFI_FIRMWARE_VOLUME_PROTOCOL *pFV; + UINT32 AuthStatus; + if (EFI_ERROR(pBS->HandleProtocol(hDevice, &guidFV, &pFV))) return EFI_NOT_FOUND; + // TODO: add support for raw files + if (EFI_ERROR(pFV->ReadSection(pFV, pFileName, EFI_SECTION_PE32, + 0, ppSource, pSize, &AuthStatus + ) + ) + ) return EFI_UNSUPPORTED; + return EFI_SUCCESS; +} + +//************************************************************************* +// +// +// Name: LFReadFile +// +// Description: +// EFI_STATUS LFReadFile(IN EFI_HANDLE hDevice, IN EFI_DEVICE_PATH_PROTOCOL* pPath, IN BOOLEAN BootPolicy, OUT VOID** ppSource, OUT UINTN *pSize) +// +// Input: +// +// Output: +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS LFReadFile(EFI_HANDLE hDevice, EFI_DEVICE_PATH_PROTOCOL* pPath, BOOLEAN BootPolicy, VOID** ppSource, UINTN *pSize) +{ + EFI_LOAD_FILE_PROTOCOL *pLoadFile; + VOID *pSource = NULL; + UINTN Size=0; + if (EFI_ERROR(pBS->HandleProtocol(hDevice, &guidLoadFile, &pLoadFile))) return EFI_NOT_FOUND; + //TODO: This is patch for SCT!!!! They return EFI_SUCCESS even though Size and pSource are zeroes!!! + //if (pLoadFile->LoadFile(pLoadFile, pPath, BootPolicy, &Size, pSource)!=EFI_BUFFER_TOO_SMALL) return EFI_NOT_FOUND; + pLoadFile->LoadFile(pLoadFile, pPath, BootPolicy, &Size, pSource); + if (!Size) return EFI_NOT_FOUND; + pSource=Malloc(Size); + if (!pSource) return EFI_OUT_OF_RESOURCES; + if (EFI_ERROR(pLoadFile->LoadFile(pLoadFile, pPath, BootPolicy, &Size, pSource)!=EFI_BUFFER_TOO_SMALL)) + { + pBS->FreePool(pSource); + return EFI_NOT_FOUND; + } + *ppSource = pSource; + *pSize = Size; + return EFI_SUCCESS; +} + +//************************************************************************* +// +// +// Name: ReadImage +// +// Description: +// EFI_STATUS ReadImage(IN BOOLEAN BootPolicy, +// IN EFI_DEVICE_PATH_PROTOCOL *FilePath, IN OUT VOID **ppSource, +// IN OUT UINTN *pSourceSize OPTIONAL, OUT UINTN *pImageSize OPTIONAL, +// OUT EFI_HANDLE *phDevice OPTIONAL, +// OUT EFI_DEVICE_PATH_PROTOCOL **ppPath OPTIONAL) +// +// Input: +// +// +// Output: +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS ReadImage ( + IN BOOLEAN BootPolicy, IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN OUT VOID **ppSource, IN OUT UINTN *pSourceSize OPTIONAL, + OUT UINTN *pImageSize OPTIONAL, + OUT EFI_HANDLE *phDevice OPTIONAL, OUT EFI_DEVICE_PATH_PROTOCOL **ppPath OPTIONAL +) +{ + EFI_HANDLE hDevice = NULL; + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *pPath = FilePath; + VOID *pSource = NULL; + if (!ppSource) return EFI_INVALID_PARAMETER; + if (!*ppSource) + { + UINTN Size; + Status = pBS->LocateDevicePath(&guidDevicePath, &pPath, &hDevice); + if (EFI_ERROR(Status)) + {//if device for the FV File is not found + //scan all FVs + UINTN Number,i; + EFI_HANDLE *Handle; + if ( pPath->Type != MEDIA_DEVICE_PATH + || pPath->SubType != MEDIA_FV_FILEPATH_DP + ) return EFI_NOT_FOUND; + Status=pBS->LocateHandleBuffer(ByProtocol, &guidFV, NULL, &Number, &Handle); + if (EFI_ERROR(Status)) return EFI_NOT_FOUND; + for(i=0; iFreePool(Handle); + if (EFI_ERROR(Status)) return Status; + } + else if (pPath->Type == MEDIA_DEVICE_PATH) + { + if(pPath->SubType == MEDIA_FV_FILEPATH_DP) + { + if (EFI_ERROR(Status = FVReadFile(hDevice, (EFI_GUID*)(pPath+1), &pSource, &Size))) return Status; + } + else if(pPath->SubType == MEDIA_FILEPATH_DP) + { + if (EFI_ERROR(Status = FSReadFile(hDevice, pPath, &pSource, &Size))) return Status; + } + } + else + { + if (EFI_ERROR(Status = LFReadFile(hDevice, pPath, BootPolicy, &pSource, &Size))) return Status; + } + if (pSourceSize) *pSourceSize = Size; + *ppSource = pSource; + } + else + { + //TODO: Should it be EFI_INVALID_PARAMETER??? + //EFI Spec does not answer the question, however, + //SCT checks for EFI_LOAD_ERROR. + if (!pSourceSize || !*pSourceSize) return EFI_LOAD_ERROR; + } + if (!IsPeImageValid(*ppSource)) return EFI_LOAD_ERROR; + if (pImageSize) *pImageSize = GetImageSize(*ppSource); + if (phDevice) *phDevice = hDevice; + if (ppPath) *ppPath = pPath; + return EFI_SUCCESS; +} + +// =================================== LIST +//List functions + +//************************************************************************* +// +// +// Name: DLIST +// +// Description: +// DLIST is a type defined structure used in an AMILIB provided +// doubly-linked list API to maintain pointers for a list's head, tail, and +// size. +// +// Fields: Name Type Description +// ------------------------------------------------------------------ +// Size UINTN Number of DLINK nodes contained by the DLIST. +// pHead DLINK* Pointer to the head node (start) of the list. +// pTail DLINK* Pointer to the tail node (end) of the list. +// +// Referrals: +// Doubly_Linked_List_Functions +// DLINK +// DListInit +// DListEmpty +// DListAdd +// DListDelete +// DListInsert +// DListEmpty +// +// Notes: +// Prototype provided in AmiDxeLib.h. See Doubly_Linked_List_Functions for +// example usage. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: DLINK +// +// Description: +// DLINK is a type defined structure used in an AMILIB provided +// doubly-linked list API which is used as a node for an entry into the list. +// +// Fields: Name Type Description +// ------------------------------------------------------------------ +// pNext DLINK* Pointer to the next node in the list. +// pPrev DLINK* Pointer to the previous node in the list. +// +// Referrals: +// Doubly_Linked_List_Functions +// DLIST +// +// Notes: +// Prototype provided in AmiDxeLib.h. See Doubly_Linked_List_Functions for +// example usage. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: DListEmpty +// +// Description: +// DlistEmpty(IN DLIST *pList) is a macro which returns NULL if the provided +// DLIST is empty. +// +// Input: +// IN DLIST *pList +// A pointer to the doubly linked list structure. +// +// Output: +// DLINK* address of the list's head; NULL if the list is empty. +// +// Modified: +// +// Referrals: +// +// Notes: +// Macro defined in AmiDxeLib.h. No validation performed on pList. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: DListInit +// +// Description: +// VOID DListInit(IN DLIST *pList) initializes the head, tail links and +// number of elements of a new linked list structure. After initializing a +// linked list with this function, the other linked list functions may be +// used to add and remove nodes from the linked list. It is up to the caller +// of this function to allocate the memory for pList. +// +// Input: +// IN DLIST *pList +// A pointer to the doubly linked list structure. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// It is up to the caller of this function to allocate the memory for pList. +// +// +//************************************************************************* + +VOID DListInit(DLIST* pList){ + pList->pHead = NULL; + pList->pTail = NULL; + pList->Size = 0; +} + +//************************************************************************* +// +// +// Name: DListAdd +// +// Description: +// VOID DListAdd(IN DLIST *pList, IN DLINK *pElement) adds the node pElement +// to the end of the doubly linked list denoted by pList. +// +// Input: +// IN DLIST *pList +// A pointer to the doubly linked list structure. +// +// IN DLINK *pElement +// A pointer to a node that is to be added at the end of the doubly linked +// list. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +VOID DListAdd(DLIST* pList, DLINK* pElement){ + pElement->pNext = NULL; + pElement->pPrev = pList->pTail; + if (!pList->pHead) pList->pHead = pElement; + else pList->pTail->pNext = pElement; + pList->pTail = pElement; + pList->Size++; +} + +//************************************************************************* +// +// +// Name: DListDelete +// +// Description: +// VOID DListDelete(IN DLIST *pList, IN DLINK *pElement) removes the node +// pElement from a doubly linked list. It is up to the caller of this +// function to release the memory used by this node if that is required. +// +// Input: +// IN DLIST *pList +// A pointer to the doubly linked list structure. +// +// IN DLINK *pElement +// A pointer to a node that is to be deleted from the end of the doubly +// linked list. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// It is up to the caller of this function to release the memory used by +// this node if that is required. +// +// +//************************************************************************* +VOID DListDelete(DLIST* pList, DLINK* pElement){ + + if (pList->pTail == pElement) pList->pTail = pElement->pPrev; + else pElement->pNext->pPrev = pElement->pPrev; + if (pList->pHead == pElement) pList->pHead = pElement->pNext; + else pElement->pPrev->pNext = pElement->pNext; + pList->Size--; +} + +//************************************************************************* +// +// +// Name: DListInsert +// +// Description: +// VOID DListInsert(IN DLIST* pList, IN DLINK* pElement, IN DLINK* pAfter) +// inserts the node pElement in the doubly linked list denoted by pList +// immediately after the node pAfter. +// +// Input: +// IN DLIST *pList +// A pointer to the doubly linked list structure. +// +// IN DLINK *pElement +// A pointer to a node that is to be added to the doubly linked list. +// +// IN DLINK *pAfter +// A pointer to a node after which pElement is to be added. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +VOID DListInsert(DLIST* pList, DLINK* pElement, DLINK* pAfter){ + pElement->pPrev = pAfter; + if (pAfter) + { + pElement->pNext = pAfter->pNext; + if (pAfter==pList->pTail) pList->pTail=pElement; + else pAfter->pNext->pPrev = pElement; + pAfter->pNext = pElement; + } + else + { + pElement->pNext = pList->pHead; + if (pList->pHead) pList->pHead->pPrev = pElement; + else pList->pTail = pElement; + pList->pHead = pElement; + } + pList->Size++; +} + +//************************************************************************* +// +// +// Name: GetEfiVariable +// +// Description: +// EFI_STATUS GetEfiVariable(IN CHAR16 *sName, IN EFI_GUID *pGuid, +// OUT UINT32 *pAttributes OPTIONAL, IN OUT UINTN *pDataSize, +// OUT VOID **ppData) reads an EFI variable with the name Name and GUID Guid. +// If variable is found, variable attributes, size, and data are returned +// using Attributes, DataSize, and Data parameters and EFI_SUCCESS is +// returned. If variable is not found, EFI_NOT_FOUND is returned. The output +// buffer is specified by a double indirection of the Data parameter. The +// input value of *Data is used to determine if the output buffer is caller +// allocated or is dynamically allocated by this functions. If the input +// value of *Data is not NULL, it indicates that the output buffer is caller +// allocated. In this case, the input value of *DataSize indicates the size +// of the caller-allocated output buffer. If the output buffer is not large +// enough to contain the variable data, it is freed and new buffer of +// sufficient size is allocated from boot services pool memory, which will be +// returned in *Data. If the input value of *Data not NULL, it indicates +// that the output buffer is allocated by GetEfiVariable routine. In this +// case, GetEfiVariable will allocate an appropriately sized buffer from boot +// services pool memory, which will be returned in *Data. +// +// Input: +// IN CHAR16 *sName +// Pointer to the null-terminated Unicode string with name of the EFI +// Variable to read. +// +// IN EFI_GUID *pGuid +// Pointer to GUID of the EFI Variable to read. +// +// OUT UINT32 *pAttributes OPTIONAL +// Pointer to the Attributes of the EFI Variable. +// +// IN OUT UINTN *pDataSize +// Pointer to the variable data size. +// +// OUT VOID **ppData +// Pointer to the variable data. +// +// Output: +// EFI_NOT_FOUND, if variable is not found. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// Malloc +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS GetEfiVariable( + IN CHAR16 *sName, IN EFI_GUID *pGuid, + OUT UINT32 *pAttributes OPTIONAL, + IN OUT UINTN *pDataSize, OUT VOID **ppData +) +{ + EFI_STATUS Status; + if (!*ppData) *pDataSize=0; + Status = pRS->GetVariable(sName, pGuid, pAttributes, pDataSize, *ppData); + if (!EFI_ERROR(Status)) return Status; + if (Status==EFI_BUFFER_TOO_SMALL) + { + if (*ppData) pBS->FreePool(*ppData); + if (!(*ppData=Malloc(*pDataSize))) return EFI_OUT_OF_RESOURCES; + Status = pRS->GetVariable(sName, pGuid, pAttributes, pDataSize, *ppData); + } + return Status; +} + +//************************************************************************* +// +// +// Name: ReadImageResource +// +// Description: +// EFI_STATUS ReadImageResource(IN EFI_HANDLE ImageHandle, +// IN EFI_GUID *pGuid, OUT VOID **ppData, OUT UINTN *pDataSize) +// +// Input: +// +// Output: +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS ReadImageResource( + EFI_HANDLE ImageHandle, EFI_GUID *pGuid, + VOID **ppData, UINTN *pDataSize +) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *pImage; + EFI_FIRMWARE_VOLUME_PROTOCOL *pFV; + UINTN i=0, DataSize; + EFI_GUID *pSectionGuid; + UINT32 Authentication; + Status=pBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, &pImage); + if (EFI_ERROR(Status)) return Status; + Status=pBS->HandleProtocol(pImage->DeviceHandle, &guidFV, &pFV); + if (EFI_ERROR(Status)) return Status; + do{ + pSectionGuid=NULL; + DataSize=0; + Status=pFV->ReadSection ( + pFV,&((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH*)(pImage->FilePath))->NameGuid, + EFI_SECTION_FREEFORM_SUBTYPE_GUID,i++, &pSectionGuid, &DataSize, + &Authentication + ); + if (!EFI_ERROR(Status)&&!guidcmp(pSectionGuid,pGuid)) break; + pBS->FreePool(pSectionGuid); + }while(!EFI_ERROR(Status)); + if (EFI_ERROR(Status)) return Status; + *ppData = pSectionGuid; + if (pDataSize) *pDataSize = DataSize; + return EFI_SUCCESS; +} + +//************************************************************************* +// +// +// Name: RegisterProtocolCallback +// +// Description: +// EFI_STATUS RegisterProtocolCallback(IN EFI_GUID *pProtocol, +// IN EFI_EVENT_NOTIFY NotifyFunction, IN VOID *pNotifyContext, +// OUT EFI_EVENT *pEvent, OUT VOID **ppRegistration) creates a notification +// event and registers that event with protocol instances specified by +// ProtocolGuid. Every time a protocol of type ProtocolGuid instance is +// installed or reinstalled, the notification function is executed. This +// function returns EFI_SUCCESS if notification event has been created. +// +// Input: +// IN EFI_GUID *pProtocol +// Supplies GUID of the protocol upon whose installation the event is fired. +// +// IN EFI_EVENT_NOTIFY NotifyFunction +// Supplies the function to notify when the event is signaled. +// +// IN VOID *pNotifyContext +// The context parameter to pass to NotifyFunction. This is an optional +// parameter and may be NULL. +// +// OUT EFI_EVENT *pEvent +// Event created event. +// +// OUT VOID **ppRegistration +// A pointer to a memory location to receive the registration value. This +// value is passed to LocateHandle() to obtain new handles that have been +// added that support the ProtocolGuid-specified protocol. +// +// Output: +// EFI_OUT_OF_RESOURCES, if space for the notification event could not be +// allocated. +// EFI_INVALID_PARAMETER, if Protocol, Event, or Registration are NULL. +// Otherwise, EFI_SUCCESS +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS RegisterProtocolCallback( + IN EFI_GUID *pProtocol, IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID *pNotifyContext, OUT EFI_EVENT *pEvent, + OUT VOID **ppRegistration +) +{ + EFI_STATUS Status; + Status = pBS->CreateEvent( + EVT_NOTIFY_SIGNAL,TPL_CALLBACK, + NotifyFunction, pNotifyContext, pEvent + ); + if (EFI_ERROR(Status)) return Status; + return pBS->RegisterProtocolNotify(pProtocol, *pEvent, ppRegistration); +} + +HII_UTILITIES_PROTOCOL *GetHiiUtilitiesInterface(){ + static HII_UTILITIES_PROTOCOL *HiiUtilities = NULL; + if ( HiiUtilities == NULL + && EFI_ERROR(pBS->LocateProtocol( + &gHiiUtilitiesProtocolGuid, NULL, &HiiUtilities + )) + //if LocateProtocol has failed, HiiUtilities is undefined. + //set it to NULL. + ) HiiUtilities = NULL; + return HiiUtilities; +} + +//************************************************************************* +// +// +// Name: HiiLibPublishPackages +// +// Description: Publishes submitted array of HII packages into HII database. +// +// Input: +// IN VOID *PackagePointers - array of pointers to the HII packages +// IN UINTN NumberOfPackages - number of pointers in the PackagePointers array +// IN EFI_GUID *PackageGuid - package list GUID +// IN EFI_HANDLE DriverHandle OPTIONAL - Handle to associate with the package list +// OUT EFI_HII_HANDLE *HiiHandle - HII handle of the package list +// +// Output: +// EFI_STATUS +// +// +//************************************************************************* +EFI_STATUS HiiLibPublishPackages( + IN VOID *PackagePointers, IN UINTN NumberOfPackages, + IN EFI_GUID *PackageGuid, IN EFI_HANDLE DriverHandle OPTIONAL, + OUT EFI_HII_HANDLE *HiiHandle +){ + HII_UTILITIES_PROTOCOL *HiiUtilities = GetHiiUtilitiesInterface(); + return + (HiiUtilities==NULL) + ? EFI_UNSUPPORTED + : HiiUtilities->PublishPackages( + PackagePointers, NumberOfPackages, + PackageGuid, DriverHandle, HiiHandle + ); +} + +//************************************************************************* +// +// +// Name: LoadStrings +// +// Description: +// EFI_STATUS LoadStrings(EFI_HANDLE ImageHandle, +// EFI_HII_HANDLE *pHiiHandle) - loads HII string packages associated with +// the specified image and publishes them to the HII database +// +// Input: +// EFI_HANDLE ImageHandle - Image Handle +// EFI_HII_HANDLE *pHiiHandle - HII package list handle +// +// Output: +// EFI_STATUS +// +// +//************************************************************************* +EFI_STATUS LoadStrings( + EFI_HANDLE ImageHandle, EFI_HII_HANDLE *pHiiHandle +) +{ + HII_UTILITIES_PROTOCOL *HiiUtilities = GetHiiUtilitiesInterface(); + return + (HiiUtilities==NULL) + ? EFI_UNSUPPORTED + : HiiUtilities->LoadStrings(ImageHandle, pHiiHandle); +} + +//************************************************************************* +// +// +// Name: LoadResources +// +// Description: +// EFI_STATUS LoadResources(EFI_HANDLE ImageHandle, +// UINTN NumberOfCallbacks, CALLBACK_INFO *pCallBack, +// INIT_HII_PACK InitFunction) - loads HII packages associated with +// the specified image and publishes them to the HII database +// +// Input: +// IN EFI_HANDLE ImageHandle - Image Handle +// IN UINTN NumberOfCallbacks - Number of the structures in the pCallBack array +// IN OUT CALLBACK_INFO *pCallBack - Array of IFR package descriptors. +// IN INIT_HII_PACK InitFunction - initialization function to be launched once resources are published. +// +// Output: +// EFI_STATUS +// +// +//************************************************************************* +EFI_STATUS LoadResources( + EFI_HANDLE ImageHandle, UINTN NumberOfCallbacks, + CALLBACK_INFO *pCallBack, INIT_HII_PACK InitFunction +) +{ + HII_UTILITIES_PROTOCOL *HiiUtilities = GetHiiUtilitiesInterface(); + return + (HiiUtilities==NULL) + ? EFI_UNSUPPORTED + : HiiUtilities->LoadResources( + ImageHandle, NumberOfCallbacks, + pCallBack, InitFunction + ); +} + +//************************************************************************* +// +// +// Name: HiiLibGetString +// +// Description: Reads string from the HII database in current language. +// +// Input: +// IN EFI_HII_HANDLE HiiHandle - Package list handle +// IN EFI_STRING_ID StringId - ID of the string to read +// IN OUT UINTN *StringSize - On entry, points to the size of the buffer pointed to by String, +// in bytes. On return, points to the length of the string, in bytes. +// OUT EFI_STRING String - Points to the output null-terminated string. +// +// Output: +// EFI_STATUS +// +// +//************************************************************************* +EFI_STATUS HiiLibGetString( + IN EFI_HII_HANDLE HiiHandle, IN STRING_REF StringId, + IN OUT UINTN *StringSize, OUT EFI_STRING String +){ + HII_UTILITIES_PROTOCOL *HiiUtilities = GetHiiUtilitiesInterface(); + return + (HiiUtilities==NULL) + ? EFI_UNSUPPORTED + : HiiUtilities->GetString(HiiHandle, StringId, StringSize, String); +} + +//************************************************************************* +// +// +// Name: HiiLibSetString +// +// Description: Updates string in the HII database in all languages supported by the package list. +// +// Input: +// IN EFI_HII_HANDLE HiiHandle - Package list handle +// IN EFI_STRING_ID StringId - ID of the string to udpate +// IN EFI_STRING String - Points to the new null-terminated string. +// +// Output: +// EFI_STATUS +// +// +//************************************************************************* +EFI_STATUS HiiLibSetString( + IN EFI_HII_HANDLE HiiHandle, IN STRING_REF StringId, IN EFI_STRING String +){ + HII_UTILITIES_PROTOCOL *HiiUtilities = GetHiiUtilitiesInterface(); + return + (HiiUtilities==NULL) + ? EFI_UNSUPPORTED + : HiiUtilities->SetString(HiiHandle, StringId,String); +} + +//************************************************************************* +// +// +// Name: HiiLibGetBrowserData +// +// Description: Retrieves uncommitted state data from the HII browser. +// Only works in UEFI 2.1 mode. +// +// Input: +// IN OUT UINTN *BufferSize - A pointer to the size of the buffer associated with Buffer. +// On input, the size in bytes of Buffer. On output, the size of data returned in Buffer. +// OUT VOID *Buffer - A data returned from an IFR browser. +// IN CONST EFI_GUID *VarStoreGuid OPTIONAL - An optional field to indicate the target variable GUID name to use. +// IN CONST CHAR16 *VarStoreName OPTIONAL - An optional field to indicate the target variable name. +// +// Output: +// EFI_STATUS +// +// +//************************************************************************* +EFI_STATUS HiiLibGetBrowserData( + IN OUT UINTN *BufferSize, OUT VOID *Buffer, + IN CONST EFI_GUID *VarStoreGuid OPTIONAL, + IN CONST CHAR16 *VarStoreName OPTIONAL +){ + HII_UTILITIES_PROTOCOL *HiiUtilities = GetHiiUtilitiesInterface(); + return + (HiiUtilities==NULL) + ? EFI_UNSUPPORTED + : HiiUtilities->GetBrowserData( + BufferSize, Buffer, VarStoreGuid, VarStoreName + ); +} + +//************************************************************************* +// +// +// Name: HiiLibSetBrowserData +// +// Description: Updates uncommitted state data of the HII browser. +// Only works in UEFI 2.1 mode. +// +// Input: +// IN UINTN BufferSize - Size of the buffer associated with Buffer. +// IN VOID *Buffer - A data to send to an IFR browser. +// IN CONST EFI_GUID *VarStoreGuid OPTIONAL - An optional field to indicate the target variable GUID name to use. +// IN CONST CHAR16 *VarStoreName OPTIONAL - An optional field to indicate the target variable name. +// +// Output: +// EFI_STATUS +// +// +//************************************************************************* +EFI_STATUS HiiLibSetBrowserData( + IN UINTN BufferSize, IN VOID *Buffer, + IN CONST EFI_GUID *VarStoreGuid, OPTIONAL + IN CONST CHAR16 *VarStoreName OPTIONAL +){ + HII_UTILITIES_PROTOCOL *HiiUtilities = GetHiiUtilitiesInterface(); + return + (HiiUtilities==NULL) + ? EFI_UNSUPPORTED + : HiiUtilities->SetBrowserData( + BufferSize, Buffer, VarStoreGuid, VarStoreName + ); +} + +//************************************************************************* +// +// +// Name: HiiLibSetString +// +// Description: Updates string in the HII database in all languages supported by the package list. +// +// Input: +// IN EFI_HII_HANDLE HiiHandle - Package list handle +// IN EFI_STRING_ID StringId - ID of the string to udpate +// IN EFI_STRING String - Points to the new null-terminated string. +// +// Output: +// EFI_STATUS +// +// +//************************************************************************* +EFI_STATUS HiiLibGetGlyphWidth( + IN CHAR16 Char, OUT UINT16 *Width +){ + HII_UTILITIES_PROTOCOL *HiiUtilities = GetHiiUtilitiesInterface(); + return + (HiiUtilities==NULL) + ? EFI_UNSUPPORTED + : HiiUtilities->GetGlyphWidth(Char, Width); +} + +//************************************************************************* +// +// +// Name: LibGetDxeSvcTbl +// +// Description: +// EFI_STATUS LibGetDxeSvcTbl(OUT DXE_SERVICES **ppDxe OPTIONAL) locates the +// DXE Service Table in the EFI System Table and returns it in ppDxe. If +// pointer is found, EFI_SUCCESS is returned. +// +// Input: +// OUT DXE_SERVICES **ppDxe OPTIONAL +// Places the address of the DXE Services Table at *ppDxe, if **ppDxe not +// equal to NULL. +// +// Output: +// EFI_INVALID_PARAMETER, if InitAmiLib() was not called prior to invoking +// this function. +// EFI_NOT_AVAILABLE_YET, if EFI Configuration Table does not have the DXE +// Services Table pointer initialized yet. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// GetEfiConfigurationTable +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS LibGetDxeSvcTbl(DXE_SERVICES **ppDxe OPTIONAL){ + //Check if we have pST pointer initialized. + if(pST==NULL) return EFI_INVALID_PARAMETER; + if(pDxe==NULL){ + //Locate Dxe Services Table + pDxe=(DXE_SERVICES*)GetEfiConfigurationTable(pST,&guidDxeSvcTbl); + if(pDxe==NULL) return EFI_NOT_AVAILABLE_YET; + } + if(ppDxe!=NULL)*ppDxe=pDxe; + return EFI_SUCCESS; +} + +//************************************************************************* +// +// +// Name: LibAllocCspResource +// +// Description: +// EFI_STATUS LibAllocCspResource(IN CSP_RES_ITEM *ResTable, +// IN UINTN ResCount, IN EFI_HANDLE ImgHandle, IN EFI_HANDLE CntrHandle) uses +// GCD services to allocate list of resources specified by ResTable. +// +// Input: +// IN CSP_RES_ITEM *ResTable +// Table of requested GCD resources. +// +// IN UINTN ResCount +// Number of elements in the ResTable. +// +// IN EFI_HANDLE ImgHandle +// Handle of the image to allocate resources to. +// +// IN EFI_HANDLE CntrHandle +// Handle of the controller to allocate resources to. +// +// Output: +// EFI_ERROR_CODE, if function fails. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// LibGetDxeSvcTbl +// +// Notes: +// +// +//************************************************************************* +#define CACHEABILITY_ATTRIBUTES \ + (EFI_MEMORY_UC|EFI_MEMORY_WC|EFI_MEMORY_WT|EFI_MEMORY_WB|EFI_MEMORY_WP) +EFI_STATUS LibAllocCspResource(CSP_RES_ITEM *ResTable, UINTN ResCount, + EFI_HANDLE ImgHandle,EFI_HANDLE CntrHandle) +{ + UINTN i; + CSP_RES_ITEM *Res=NULL; + EFI_STATUS Status=0; + UINT64 top=0, bot=-1, len=0; + UINTN uccnt=0, memcnt=0; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR mdsc; + EFI_GCD_IO_SPACE_DESCRIPTOR idsc; +//-------------------------------- + //Get Dxe Services Table + if(pDxe==NULL){ + Status=LibGetDxeSvcTbl(NULL); + if(EFI_ERROR(Status)){ + TRACE((-1, "Dxe Services Table could not be found! Status = %r",Status)); + ASSERT_EFI_ERROR(Status); + return Status; + } + } + //Add this Space as MMIO to the GCD + for(i=0; iAttributes==-1){ + Status=pDxe->AddIoSpace(Res->ResType,Res->ResBase,Res->ResLength); + TRACE((-1, "GCD: AddI/O")); + } else { + //Some attempt to optimize region caching + //we will try to group some regions based on their cache requirements. + memcnt++; + if(Res->Attributes & EFI_MEMORY_UC) uccnt++; + if((Res->ResBase+Res->ResLength) > top ) top=Res->ResBase+Res->ResLength; + if(Res->ResBase < bot) bot=Res->ResBase; + Status=pDxe->AddMemorySpace(Res->ResType,Res->ResBase,Res->ResLength,GCD_COMMON_MMIO_CAPS); + TRACE((-1, "GCD: AddMem")); + } + TRACE((-1, "Space B=%lX, L=%X, i=%d, S=%r\n",Res->ResBase,Res->ResLength,i,Status)); + + //Allocate the Space + if(Res->Attributes==-1) { + //Check Gcd IO we are trying to Allocate + Status=pDxe->GetIoSpaceDescriptor(Res->ResBase, &idsc); + if(idsc.ImageHandle != NULL) continue; + //If Space is not allocated but marked as different type of Space - use the one we got + else if(idsc.GcdIoType!=Res->ResType /*&& + idsc.BaseAddress<=Res->ResBase && + (idsc.BaseAddress+idsc.Length) >= (Res->ResBase+Res->ResLength)*/ + ) Res->ResType=idsc.GcdIoType; + Status=pDxe->AllocateIoSpace(EfiGcdAllocateAddress, + Res->ResType,0, Res->ResLength, &Res->ResBase, ImgHandle, CntrHandle); + TRACE((-1, "GCD: AllocI/O")); + } else { + //Check Gcd Memory we are trying to Allocate + Status=pDxe->GetMemorySpaceDescriptor(Res->ResBase, &mdsc); + //the resource has been allocated earlier by MRC or trough HOB + if(mdsc.ImageHandle != NULL) continue; + //If Space is not allocated but marked as different type of Space - use the one we got + else if(mdsc.GcdMemoryType!=Res->ResType /*&& + mdsc.BaseAddress<=Res->ResBase && + (mdsc.BaseAddress+mdsc.Length) >= (Res->ResBase+Res->ResLength)*/ + ) Res->ResType=mdsc.GcdMemoryType; + + Status=pDxe->AllocateMemorySpace(EfiGcdAllocateAddress, + Res->ResType, 0, Res->ResLength, &Res->ResBase, ImgHandle, CntrHandle); + TRACE((-1, "GCD: AllocMem")); + } + TRACE((-1, "Space B=%lX, L=%X, i=%d, S=%r\n",Res->ResBase,Res->ResLength,i,Status)); + if(EFI_ERROR(Status)){ + ASSERT_EFI_ERROR(Status); + return Status; + } + } //for loop for allocation + + //this is the case when entire region suppose to be uncached + if(memcnt && (memcnt==uccnt)){ + EFI_GCD_MEMORY_SPACE_DESCRIPTOR md; + UINT64 newb, newt, newl; + //---------------------- + //Adjust Caching Attribute Address to fit PAGES + len=top-bot; + if(bot & EFI_PAGE_MASK){ + bot&=(~EFI_PAGE_MASK); + len = (len&(~EFI_PAGE_MASK))+EFI_PAGE_SIZE; + } + if(len & EFI_PAGE_MASK) len = (len&(~EFI_PAGE_MASK))+EFI_PAGE_SIZE; + + //Now we must apply Caching attributes but must be wery careful + //not to clean RT attributes if it was set by earlier call + TRACE((-1, "GCD: SpaceAttr (UC ALL) B=%lX; L=%lX; \n",bot,top-bot)); + + newb=bot; + + for(;;){ + Status=pDxe->GetMemorySpaceDescriptor(newb,&md); + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) break; + + newt=md.BaseAddress+md.Length; + if(newt>=top) newt=top; + newl=newt-newb; + + if(md.Attributes & EFI_MEMORY_UC){ + TRACE((-1, "GCD:(UC ALL) skipping")); + } else { + md.Attributes|=EFI_MEMORY_UC; + Status=pDxe->SetMemorySpaceAttributes(newb,newl, md.Attributes); + TRACE((-1, "GCD:(UC ALL) setting ")); + } + TRACE((-1," B=%lX, L=%lX, A=%lX; S=%r\n",newb,newl,md.Attributes, Status)); + + if(newt>=top) break; + newb=newt; + } + + } + //set cacheability attributes + for(i=0; iSetMemorySpaceAttributes(ResTable[i].ResBase,ResTable[i].ResLength,ResTable[i].Attributes); + TRACE((-1, "GCD: SpaceAttr A=%lX B=%lX, L=%X, i=%X, S=%r\n", + ResTable[i].Attributes, ResTable[i].ResBase, ResTable[i].ResLength,i,Status)); + if EFI_ERROR(Status){ + //Attempt to set attributes failed; + //Let's set non-cacheability attributes + UINT64 attr=ResTable[i].Attributes & ~CACHEABILITY_ATTRIBUTES; + //If all descriptors are uncacheable add US attribute + if(memcnt==uccnt) attr|=EFI_MEMORY_UC; + Status=pDxe->SetMemorySpaceAttributes(ResTable[i].ResBase,ResTable[i].ResLength, attr); + } + } + return Status; +} + +//************************************************************************* +// +// +// Name: AllocCspResource +// +// Description: +// EFI_STATUS AllocCspResource(IN DXE_SERVICES *Dxe, +// IN CSP_RES_ITEM *ResTable, IN UINTN ResCount, IN EFI_HANDLE ImgHandle, +// IN EFI_HANDLE CntrHandle, IN BOOLEAN AddSpace) provides compatibility with +// core 4.5.3; acts as a wrapper for LibAllocCspResource. +// +// Input: +// IN DXE_SERVICES *Dxe +// Unused. +// +// IN CSP_RES_ITEM *ResTable +// Table of requested GCD resources. +// +// IN UINTN ResCount +// Number of elements in the ResTable. +// +// IN EFI_HANDLE ImgHandle +// Handle of the image to allocate resources to. +// +// IN EFI_HANDLE CntrHandle +// Handle of the controller to allocate resources to. +// +// IN BOOLEAN AddSpace +// Unused. +// +// Output: +// EFI_ERROR_CODE, if function fails. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// LibAllocCspResource +// +// Notes: +// Use LibAllocCspResource unless you are using core 4.5.3 or older. +// +// +//************************************************************************* +EFI_STATUS AllocCspResource(DXE_SERVICES *Dxe, CSP_RES_ITEM *ResTable, UINTN ResCount, + EFI_HANDLE ImgHandle,EFI_HANDLE CntrHandle, BOOLEAN AddSpace) +{ + return LibAllocCspResource(ResTable, ResCount,ImgHandle, CntrHandle); +} + +//************************************************************************* +// +// +// Name: GetSmstConfigurationTable +// +// Description: +// VOID *GetEfiConfigurationTable( IN EFI_GUID *TableGuid) +// retrieves a pointer to the system configuration table +// from the SMM System Table based on a specified GUID. If a match is found, +// then a pointer to the configuration table is returned. If a matching GUID +// is not found, then NULL is returned. +// +// Input: +// IN EFI_GUID *TableGuid +// Pointer to table's GUID type. +// +// Output: +// VOID* pointer to configuration table if a match is found; otherwise NULL. +// +// Referrals: +// guidcmp +// +// Notes: +// This function only works in SMM. It relies on global initialization performed +// by InitSmmHandler(or InitSmmHandlerEx) function. +// +// +//************************************************************************* +VOID* GetSmstConfigurationTableFramework(IN EFI_GUID *TableGuid){ + EFI_CONFIGURATION_TABLE *Table; + UINTN i; + + ASSERT(pSmstFramework!=NULL); //pSmstFramework must be initialized with the call to InitSmiHandler + if (pSmstFramework==NULL) return NULL; + Table = pSmstFramework->SmmConfigurationTable; + i = pSmstFramework->NumberOfTableEntries; + + for (;i;--i,++Table) + { + if (guidcmp(&Table->VendorGuid,TableGuid)==0) + return Table->VendorTable; + } + return NULL; +} + +#if PI_SPECIFICATION_VERSION >= 0x0001000A +VOID* GetSmstConfigurationTablePi(IN EFI_GUID *TableGuid){ + EFI_CONFIGURATION_TABLE *Table; + UINTN i; + + ASSERT(pSmstPi!=NULL); //pSmstFramework must be initialized with the call to InitSmiHandler + if (pSmstPi==NULL) return NULL; + Table = pSmstPi->SmmConfigurationTable; + i = pSmstPi->NumberOfTableEntries; + + for (;i;--i,++Table) + { + if (guidcmp(&Table->VendorGuid,TableGuid)==0) + return Table->VendorTable; + } + return NULL; +} +#endif + +//************************************************************************* +// +// +// Name: InitSmmHandler +// +// Description: +// EFI_STATUS InitSmmHandler(IN EFI_HANDLE ImageHandle, +// IN EFI_SYSTEM_TABLE *SystemTable, +// IN EFI_STATUS (*InSmmFunction)(EFI_HANDLE ImageHandle, +// EFI_SYSTEM_TABLE *SystemTable), +// IN EFI_STATUS (*NotInSmmFunction)(EFI_HANDLE ImageHandle, +// EFI_SYSTEM_TABLE *SystemTable) OPTIONAL) first calls the provided +// NotInSmmFunction (if provided), then runs the InSmmFunction in SMM. +// +// Input: +// IN EFI_HANDLE ImageHandle +// This driver's image handle. +// +// IN EFI_SYSTEM_TABLE *SystemTable +// Pointer to the system table. +// +// IN EFI_STATUS (*InSmmFunction)(EFI_HANDLE ImageHandle EFI_SYSTEM_TABLE *SystemTable) +// Pointer to the function to be run inside SMM. +// +// IN EFI_STATUS (*NotInSmmFunction)(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) OPTIONAL +// Pointer to the function to be run outside SMM. +// +// Output: +// EFI_NOT_FOUND, if the SMM Base Protocol is not installed. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS InitSmmHandlerFramework( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable, + IN EFI_STATUS (*InSmmFunction)(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable), + IN EFI_STATUS (*NotInSmmFunction)(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) OPTIONAL +) +{ + BOOLEAN InSmm; + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath; + EFI_DEVICE_PATH_PROTOCOL *FilePath; + EFI_HANDLE Handle; + VOID *p; + + InitAmiLib(ImageHandle,SystemTable); + Status = pBS->LocateProtocol(&gEfiSmmBaseProtocolGuid, NULL, &pSmmBaseFramework); + if (EFI_ERROR(Status)) return Status; + + pSmmBaseFramework->InSmm(pSmmBaseFramework, &InSmm); + + if (!InSmm) { + //First do non InSmm initialization. + if (NotInSmmFunction) { + Status = NotInSmmFunction(ImageHandle,SystemTable); + if (EFI_ERROR(Status)) return Status; + } + + // Get this driver's image's FilePath + Status = pBS->HandleProtocol( + ImageHandle, &gEfiLoadedImageProtocolGuid, &LoadedImage); + if (EFI_ERROR(Status)) return Status; + + Status = pBS->HandleProtocol( + LoadedImage->DeviceHandle, &guidDevicePath, (VOID*)&ImageDevicePath + ); + if (EFI_ERROR(Status)) return Status; + + FilePath = DPAdd( + ImageDevicePath, LoadedImage->FilePath + ); + + //Load the image in Smram. The driver is called again in smm. + Status = pSmmBaseFramework->Register(pSmmBaseFramework, FilePath, NULL, 0, &Handle, FALSE); + pBS->FreePool(FilePath); + return Status; + } + + Status = pSmmBaseFramework->GetSmstLocation(pSmmBaseFramework,&pSmstFramework); + if (EFI_ERROR(Status)) return Status; + + p = GetSmstConfigurationTable(&SmmRsTableGuid); + if (p!=NULL) pRS = p; + IsInSmm = TRUE; + IsAtRuntime = FALSE; + LibInitStatusCodePtr(); + IsAtRuntime = TRUE; + return InSmmFunction(ImageHandle,SystemTable); +} + +#if PI_SPECIFICATION_VERSION >= 0x0001000A +EFI_STATUS InitSmmHandlerPi( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable, + IN EFI_STATUS (*InSmmFunction)(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable), + IN EFI_STATUS (*NotInSmmFunction)(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) OPTIONAL +) +{ + BOOLEAN InSmm; + EFI_STATUS Status; + VOID *p; + + InitAmiLib(ImageHandle,SystemTable); + Status = pBS->LocateProtocol(&gEfiSmmBase2ProtocolGuid, NULL, &pSmmBasePi); + if (!EFI_ERROR(Status)) pSmmBasePi->InSmm(pSmmBasePi, &InSmm); + + if (EFI_ERROR(Status) || !InSmm) { + //First do non InSmm initialization. + if (NotInSmmFunction) { + Status = NotInSmmFunction(ImageHandle,SystemTable); + } + return Status; + } + + Status = pSmmBasePi->GetSmstLocation(pSmmBasePi,&pSmstPi); + if (EFI_ERROR(Status)) return Status; + + p = GetSmstConfigurationTablePi(&SmmRsTableGuid); + if (p!=NULL) pRS = p; + IsInSmm = TRUE; + IsAtRuntime = FALSE; + LibInitStatusCodePtr(); + IsAtRuntime = TRUE; + return InSmmFunction(ImageHandle,SystemTable); +} +#endif + +EFI_STATUS InitAmiSmmLibFramework( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable) +{ + BOOLEAN InSmm; + EFI_STATUS Status; + VOID *p; + + InitAmiLib(ImageHandle,SystemTable); + if(pSmmBaseFramework==NULL){ + Status = pBS->LocateProtocol(&gEfiSmmBaseProtocolGuid, NULL, &pSmmBaseFramework); + if (EFI_ERROR(Status)) return Status; + } + + pSmmBaseFramework->InSmm(pSmmBaseFramework, &InSmm); + + if(InSmm){ + Status = pSmmBaseFramework->GetSmstLocation(pSmmBaseFramework,&pSmstFramework); + if (EFI_ERROR(Status)) return Status; + + p = GetSmstConfigurationTable(&SmmRsTableGuid); + if (p!=NULL) pRS = p; + IsAtRuntime = FALSE; + IsInSmm = TRUE; + LibInitStatusCodePtr(); + IsAtRuntime = TRUE; + } + return Status; +} + +#if PI_SPECIFICATION_VERSION >= 0x0001000A +EFI_STATUS InitAmiSmmLibPi( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable) +{ + BOOLEAN InSmm; + EFI_STATUS Status; + VOID *p; + + + InitAmiLib(ImageHandle,SystemTable); + if(pSmmBasePi==NULL){ + Status = pBS->LocateProtocol(&gEfiSmmBase2ProtocolGuid, NULL, &pSmmBasePi); + if (EFI_ERROR(Status)) return Status; + } + + pSmmBasePi->InSmm(pSmmBasePi, &InSmm); + + if(InSmm){ + Status = pSmmBasePi->GetSmstLocation(pSmmBasePi,&pSmstPi); + if (EFI_ERROR(Status)) return Status; + + p = GetSmstConfigurationTablePi(&SmmRsTableGuid); + if (p!=NULL) pRS = p; + IsInSmm = TRUE; + IsAtRuntime = FALSE; + LibInitStatusCodePtr(); + IsAtRuntime = TRUE; + } + return Status; +} +#endif + +static EFI_STATUS InitSmmCallback(IN EFI_EVENT Event, IN VOID *Context) +{ + EFI_DEVICE_PATH_PROTOCOL *FilePath; + EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_HANDLE Handle; + EFI_STATUS Status; + + Status = pBS->LocateProtocol(&gEfiSmmBaseProtocolGuid, NULL, &pSmmBaseFramework); + if (EFI_ERROR(Status)) return Status; + + // Get this driver's image's FilePath + Status = pBS->HandleProtocol( + TheImageHandle, &gEfiLoadedImageProtocolGuid, &LoadedImage + ); + if (EFI_ERROR(Status)) return Status; + + Status = pBS->HandleProtocol( + LoadedImage->DeviceHandle, &guidDevicePath, (VOID*)&ImageDevicePath + ); + if (EFI_ERROR(Status)) return Status; + + FilePath = DPAdd( + ImageDevicePath, LoadedImage->FilePath + ); + + //Load the image in Smram. The driver is called again in smm. + Status = pSmmBaseFramework->Register(pSmmBaseFramework, FilePath, NULL, 0, &Handle, FALSE); + pBS->FreePool(FilePath); + return Status; +} + +//************************************************************************* +// +// +// Name: InitSmmHandlerEx +// +// Description: +// The function is similar to InitSmmHandler function. +// The difference between the two is handling of missing SmmBase protocol. +// If SmmBase protocol is not available, InitSmmHandler function returns error. +// This function registers callback and loads module to SMM once SmmBase is available. +// +// Input: +// IN EFI_HANDLE ImageHandle +// This driver's image handle. +// +// IN EFI_SYSTEM_TABLE *SystemTable +// Pointer to the system table. +// +// IN EFI_STATUS (*InSmmFunction)(EFI_HANDLE ImageHandle EFI_SYSTEM_TABLE *SystemTable) +// Pointer to the function to be run inside SMM. +// +// IN EFI_STATUS (*NotInSmmFunction)(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) OPTIONAL +// Pointer to the function to be run outside SMM. +// +// Output: +// EFI_NOT_FOUND, if the SMM Base Protocol is not installed. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS InitSmmHandlerExFramework( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable, + IN EFI_STATUS (*InSmmFunction)(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable), + IN EFI_STATUS (*NotInSmmFunction)(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) OPTIONAL +) +{ + static BOOLEAN Registered = FALSE; + BOOLEAN InSmm = FALSE; + EFI_STATUS Status, SmmBaseStatus; + EFI_EVENT SmmBaseEvent; + VOID *p; + + InitAmiLib(ImageHandle,SystemTable); + SmmBaseStatus = pBS->LocateProtocol(&gEfiSmmBaseProtocolGuid, NULL, &pSmmBaseFramework); + + if (!EFI_ERROR(SmmBaseStatus)) pSmmBaseFramework->InSmm(pSmmBaseFramework, &InSmm); + if (EFI_ERROR(SmmBaseStatus) || !InSmm) + { + //First do non InSmm initialization. + if (NotInSmmFunction) { + Status = NotInSmmFunction(ImageHandle,SystemTable); + if (EFI_ERROR(Status)) return Status; + } + if (Registered) return Status; + if (EFI_ERROR(SmmBaseStatus)) + Status = RegisterProtocolCallback(&gEfiSmmBaseProtocolGuid, InitSmmCallback, + NULL, &SmmBaseEvent, &p + ); + else + Status = InitSmmCallback(NULL, NULL); + if (!EFI_ERROR(Status)) Registered = TRUE; + return Status; + } + Status = pSmmBaseFramework->GetSmstLocation(pSmmBaseFramework,&pSmstFramework); + if (EFI_ERROR(Status)) return Status; + p = GetSmstConfigurationTable(&SmmRsTableGuid); + if (p!=NULL) pRS = p; + IsAtRuntime = FALSE; + IsInSmm = TRUE; + LibInitStatusCodePtr(); + IsAtRuntime = TRUE; + return InSmmFunction(ImageHandle,SystemTable); +} + +//************************************************************************* +// +// +// Name: DummyFunction +// +// Description: +// VOID DummyFunction(IN EFI_EVENT Event, IN VOID *Context) is an empty +// VOID function which does nothing. +// +// Input: +// IN EFI_EVENT Event +// Unused. +// +// IN VOID *Context +// Unused. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +VOID DummyFunction(IN EFI_EVENT Event, IN VOID *Context) {} + +//************************************************************************* +// +// +// Name: CreateReadyToBootEvent +// +// Description: +// EFI_STATUS CreateReadyToBootEvent(IN EFI_TPL NotifyTpl, +// IN EFI_EVENT_NOTIFY NotifyFunction, IN VOID *pNotifyContext, +// OUT EFI_EVENT *pEvent) creates an EFI event in the Ready To Boot Event +// Group and allows the caller to specify a notification function. Prior to +// UEFI 2.0 this was done via a non-standard UEFI extension, and this library +// abstracts the implementation mechanism of this event from the caller. +// +// Input: +// IN EFI_TPL NotifyTpl +// The task priority level of the event. +// +// IN EFI_EVENT_NOTIFY NotifyFunction +// The notification function to call when the event is signaled. +// +// IN VOID *pNotifyContext +// The content to pass to NotifyFunction when the event is signaled. +// +// OUT EFI_EVENT *pEvent +// Return the event that was created. +// +// Output: +// EFI_INVALID_PARAMETER, if the input parameters are incorrect. +// EFI_OUT_OF_RESOURCES, if the event could not be allocated. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS CreateReadyToBootEvent( + IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID *pNotifyContext, OUT EFI_EVENT *pEvent +) +{ +#if EFI_SPECIFICATION_VERSION<0x20000 + return pBS->CreateEvent( + (NotifyFunction) ? EFI_EVENT_SIGNAL_READY_TO_BOOT + : (EFI_EVENT_SIGNAL_READY_TO_BOOT | EFI_EVENT_NOTIFY_SIGNAL_ALL), + NotifyTpl, NotifyFunction, pNotifyContext, pEvent + ); +#else + static EFI_GUID guidReadyToBoot = EFI_EVENT_GROUP_READY_TO_BOOT; + return pBS->CreateEventEx( + EVT_NOTIFY_SIGNAL, NotifyTpl, + (NotifyFunction) ? NotifyFunction : DummyFunction, + pNotifyContext, &guidReadyToBoot, + pEvent + ); +#endif +} + +//************************************************************************* +// +// +// Name: CreateLegacyBootEvent +// +// Description: +// EFI_STATUS CreateLegacyBootEvent(IN EFI_TPL NotifyTpl, +// IN EFI_EVENT_NOTIFY NotifyFunction, IN VOID *pNotifyContext, +// OUT EFI_EVENT *pEvent) creates an EFI event in the Legacy Boot Event Group +// and allows the caller to specify a notification function. Prior to +// UEFI 2.0 this was done via a non-standard UEFI extension, and this library +// abstracts the implementation mechanism of this event from the caller. +// +// Input: +// IN EFI_TPL NotifyTpl +// The task priority level of the event. +// +// IN EFI_EVENT_NOTIFY NotifyFunction +// The notification function to call when the event is signaled. +// +// IN VOID *pNotifyContext +// The content to pass to NotifyFunction when the event is signaled. +// +// OUT EFI_EVENT *pEvent +// Return the event that was created +// +// Output: +// EFI_INVALID_PARAMETER, if the input parameters are incorrect. +// EFI_OUT_OF_RESOURCES, if the event could not be allocated. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS CreateLegacyBootEvent( + IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID *pNotifyContext, OUT EFI_EVENT *pEvent +) +{ +#if EFI_SPECIFICATION_VERSION<0x20000 + return pBS->CreateEvent( + (NotifyFunction) ? EFI_EVENT_SIGNAL_LEGACY_BOOT + : (EFI_EVENT_SIGNAL_LEGACY_BOOT | EFI_EVENT_NOTIFY_SIGNAL_ALL), + NotifyTpl, NotifyFunction, pNotifyContext, pEvent + ); +#else + static EFI_GUID guidLegacyBoot = EFI_EVENT_LEGACY_BOOT_GUID; + return pBS->CreateEventEx( + EVT_NOTIFY_SIGNAL, NotifyTpl, + (NotifyFunction) ? NotifyFunction : DummyFunction, + pNotifyContext, &guidLegacyBoot, + pEvent + ); +#endif +} + +//************************************************************************* +// +// +// Name: GetBootMode +// +// Description: +// EFI_BOOT_MODE GetBootMode() returns current boot mode. If no boot mode +// information is available, BOOT_WITH_FULL_CONFIGURATION is returned. +// +// Input: +// VOID. +// +// Output: +// BOOT_WITH_FULL_CONFIGURATION, if no boot mode information is available. +// Otherwise, the current EFI_BOOT_MODE. +// +// Modified: +// +// Referrals: +// GetEfiConfigurationTable +// +// Notes: +// +// +//************************************************************************* +EFI_BOOT_MODE GetBootMode() +{ + static EFI_GUID guidHob = HOB_LIST_GUID; + EFI_HOB_HANDOFF_INFO_TABLE *pHit; + //Get Boot Mode + pHit = GetEfiConfigurationTable(pST, &guidHob); + return (pHit) ? pHit->BootMode : BOOT_WITH_FULL_CONFIGURATION; +} + +//********************************************************************** +// PERFORMANCE FUNCTIONS AND STRUCTURES +//********************************************************************** + +#define EFI_PERF_PEI_ENTRY_MAX_NUM 50 + +typedef struct { + CHAR8 Token[EFI_PERF_PDBFILENAME_LENGTH]; + UINT32 Duration; +} EFI_PERF_DATA; + +typedef struct { + UINT64 BootToOs; + UINT64 S3Resume; + UINT32 S3EntryNum; + EFI_PERF_DATA S3Entry[EFI_PERF_PEI_ENTRY_MAX_NUM]; + UINT64 CpuFreq; + UINT64 BDSRaw; + UINT32 Count; + UINT32 Signiture; +} EFI_PERF_HEADER; + +//************************************************************************* +// +// +// Name: PERF_START +// +// Description: +// PERF_START(Handle, Token, Host, Ticker) is a macro which invokes the +// StartMeasure function to log a timer entry for measuring performance if +// the DXE_PERFORMANCE SDL token is turned on. If the DXE_PERFORMANCE SDL +// token is turned off, the macro does nothing. +// +// Input: +// IN EFI_HANDLE Handle +// Handle to measure. +// +// IN CHAR16 *Token +// Token to measure. +// +// IN CHAR16 *Host +// Host to measure. +// +// IN UINT64 Ticker +// Set gauge data's StartTick. If 0, StartTick is current timer value. +// +// Output: +// EFI_OUT_OF_RESOURCES, if not enough memory available for new item. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// StartMeasure +// +// Notes: +// This macro is defined in AmiDxeLib.h. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: StartMeasure +// +// Description: +// EFI_STATUS StartMeasure (IN EFI_HANDLE Handle, IN CHAR16 *Token, +// IN CHAR16 *Host, IN UINT64 Ticker) starts timing on a specified handle, +// token and host, with Ticker as the start tick. See notes for proper +// usage. +// +// Input: +// IN EFI_HANDLE Handle +// Handle to measure. +// +// IN CHAR16 *Token +// Token to measure. +// +// IN CHAR16 *Host +// Host to measure. +// +// IN UINT64 Ticker +// Set gauge data's StartTick. If 0, StartTick is current timer. +// +// Output: +// EFI_OUT_OF_RESOURCES, if not enough memory available for new item. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// PERF_START +// +// Notes: +// To properly use this function, use the PERF_START macro defined in +// AmiDxeLib.h; this allows the DXE_PERFORMANCE SDL token to control +// enabling and disabling performance measurement in DXE. +// +// +//************************************************************************* +EFI_STATUS StartMeasure ( + IN EFI_HANDLE Handle, IN CHAR16 *Token, + IN CHAR16 *Host, IN UINT64 Ticker +) +{ + EFI_STATUS Status; + EFI_PERFORMANCE_PROTOCOL *Perf; + + Status = pBS->LocateProtocol (&gEfiPerformanceProtocolGuid, NULL, (VOID **) &Perf); + if (EFI_ERROR (Status)) { + return Status; + } + return Perf->StartGauge (Perf, Handle, Token, Host, Ticker); +} + +//************************************************************************* +// +// +// Name: PERF_END +// +// Description: +// PERF_END(Handle, Token, Host, Ticker) is a macro which invokes the +// EndMeasure function to stop timing for a performance entry in order to +// determine performance if the DXE_PERFORMANCE SDL token is turned on. If +// the DXE_PERFORMANCE SDL token is turned off, the macro does nothing. +// +// Input: +// IN EFI_HANDLE Handle +// Handle to stop. +// +// IN CHAR16 *Token +// Token to stop. +// +// IN CHAR16 *Host +// Host to stop. +// +// IN UINT64 Ticker +// End tick for timing; if 0, then EndMeasure gets current timer. +// +// Output: +// EFI_NOT_FOUND, if node or Performance Protocol not found. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// EndMeasure +// +// Notes: +// This macro is defined in AmiDxeLib.h. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: EndMeasure +// +// Description: +// EFI_STATUS EndMeasure(IN EFI_HANDLE Handle, IN CHAR16 *Token, +// IN CHAR16 *Host, IN UINT64 Ticker) ends timing on a specified handle, +// token and host, with Ticker as the end tick. See notes for proper usage. +// +// Input: +// IN EFI_HANDLE Handle +// Handle to stop. +// +// IN CHAR16 *Token +// Token to stop. +// +// IN CHAR16 *Host +// Host to stop. +// +// IN UINT64 Ticker +// End tick for timing; if 0, then EndMeasure gets current timer. +// +// Output: +// EFI_NOT_FOUND, if node or Performance Protocol not found. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// PERF_END +// +// Notes: +// To properly use this function, use the PERF_END macro defined in +// AmiDxeLib.h; this allows the DXE_PERFORMANCE SDL token to control +// enabling and disabling performance measurement in DXE. +// +// +//************************************************************************* +EFI_STATUS EndMeasure ( + IN EFI_HANDLE Handle, IN CHAR16 *Token, + IN CHAR16 *Host, IN UINT64 Ticker +) +{ + EFI_STATUS Status; + EFI_PERFORMANCE_PROTOCOL *Perf; + + Status = pBS->LocateProtocol (&gEfiPerformanceProtocolGuid, NULL, (VOID **) &Perf); + if (Status != EFI_SUCCESS) { + return Status; + } + return (Perf->EndGauge( Perf, Handle, Token, Host, Ticker)) ; +} + +//************************************************************************* +// +// +// Name: PERF_CODE +// +// Description: +// PERF_CODE(Code) is a macro which places the provided code block into the +// requested location if the DXE_PERFORMANCE SDL token is turned on. If the +// DXE_PERFORMANCE SDL token is turned off, the macro inserts nothing. +// +// Input: +// Code +// Block or line of code to be inserted if the DXE_PERFORMANCE SDL token is +// enabled. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// EndMeasure +// +// Notes: +// This macro is defined in AmiDxeLib.h. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: WriteBootToOsPerformanceData +// +// Description: +// VOID WriteBootToOsPerformanceData() allocates a block of memory and +// writes performance data into it. +// +// Input: +// VOID. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// GetCpuTimer +// Div64 +// Strcpy +// +// Notes: +// This function must only be called once; by default, it is called by BDS. +// +// +//************************************************************************* +VOID WriteBootToOsPerformanceData (){ + static EFI_PHYSICAL_ADDRESS AcpiLowMemoryBase = 0x00000000ffffffff; + static BOOLEAN FirstCall = TRUE; + + EFI_STATUS Status; + EFI_CPU_ARCH_PROTOCOL *Cpu; + EFI_PERFORMANCE_PROTOCOL *DrvPerf; + UINT32 AcpiLowMemoryLength; + UINT32 LimitCount; + EFI_PERF_HEADER PerfHeader; + EFI_PERF_DATA PerfData; + EFI_GAUGE_DATA *DumpData; + EFI_HANDLE *Handles; + UINTN NoHandles; + UINT8 *Ptr; + UINT8 *PdbFileName; + UINT32 Index; + UINT64 Ticker; + UINT64 Freq; + UINT32 Duration; + UINT64 CurrentTicker; + UINT64 TimerPeriod; + EFI_GUID gEfiGlobalVariableGuid = EFI_GLOBAL_VARIABLE; + IN CHAR8 *Dest; + IN CHAR16 *Src; + + + + // Retrive time stamp count as early as possilbe + Ticker = GetCpuTimer (); + + // Allocate a block of memory that contain performance data to OS for the first call + if(FirstCall) + { + Status = pBS->AllocatePages ( + AllocateMaxAddress, + EfiRuntimeServicesData, + 4, + &AcpiLowMemoryBase + ); + if (EFI_ERROR (Status)) { + return ; + } + } + + AcpiLowMemoryLength = EFI_PAGES_TO_SIZE(4); + + Ptr = (UINT8 *) ((UINT32) AcpiLowMemoryBase + sizeof (EFI_PERF_HEADER)); + LimitCount = (AcpiLowMemoryLength - sizeof (EFI_PERF_HEADER)) / sizeof (EFI_PERF_DATA); + + // Get performance architecture protocol + Status = pBS->LocateProtocol ( + &gEfiPerformanceProtocolGuid, + NULL, + &DrvPerf + ); + if (EFI_ERROR (Status)) { + pBS->FreePages (AcpiLowMemoryBase, 4); + return ; + } + // Initialize performance data structure + pBS->SetMem (&PerfHeader, sizeof (EFI_PERF_HEADER), 0); + + // Get CPU frequency + Status = pBS->LocateProtocol ( + &gEfiCpuArchProtocolGuid, + NULL, + &Cpu + ); + if (EFI_ERROR (Status)) { + pBS->FreePages (AcpiLowMemoryBase, 4); + return ; + } + // Get Cpu Frequency + Status = Cpu->GetTimerValue (Cpu, 0, &(CurrentTicker), &TimerPeriod); + if (EFI_ERROR (Status)) { + pBS->FreePages (AcpiLowMemoryBase, 4); + return ; + } + + Freq = Div64(1000000000000, (UINTN) TimerPeriod, NULL); + PerfHeader.CpuFreq = Freq; + + // Record current raw performance data + PerfHeader.BDSRaw = Ticker; + + // Put Detailed performance data into memory + Handles = NULL; + Status = pBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &NoHandles, + &Handles + ); + if (EFI_ERROR (Status)) { + pBS->FreePages (AcpiLowMemoryBase, 1); + return ; + } + + // Get DXE drivers performance + for (Index = 0; Index < NoHandles; Index++) { + Ticker = 0; + PdbFileName = NULL; + DumpData = DrvPerf->GetGauge ( + DrvPerf, // Context + NULL, // Handle + NULL, // Token + NULL, // Host + NULL // PrecGauge + ); + while (DumpData) { + if (DumpData->Handle == Handles[Index]) { + PdbFileName = &(DumpData->PdbFileName[0]); + if (DumpData->StartTick < DumpData->EndTick) { + Ticker += (DumpData->EndTick - DumpData->StartTick); + } + } + + DumpData = DrvPerf->GetGauge ( + DrvPerf, // Context + NULL, // Handle + NULL, // Token + NULL, // Host + DumpData // PrecGauge + ); + } + + Duration = (UINT32) Div64 ( + Ticker, + (UINT32) Freq, + NULL + ); + + if (Duration > 0) { + pBS->SetMem (&PerfData, sizeof (EFI_PERF_DATA), 0); + + if (PdbFileName != NULL) { + Strcpy (PerfData.Token, PdbFileName); + } + + PerfData.Duration = Duration; + + pBS->CopyMem (Ptr, &PerfData, sizeof (EFI_PERF_DATA)); + Ptr += sizeof (EFI_PERF_DATA); + + PerfHeader.Count++; + if (PerfHeader.Count == LimitCount) { + goto Done; + } + } + } + + pBS->FreePool (Handles); + + // Get inserted performance data + DumpData = DrvPerf->GetGauge ( + DrvPerf, // Context + NULL, // Handle + NULL, // Token + NULL, // Host + NULL // PrecGauge + ); + while (DumpData) { + if ((DumpData->Handle) || (DumpData->StartTick > DumpData->EndTick)) { + DumpData = DrvPerf->GetGauge ( + DrvPerf, // Context + NULL, // Handle + NULL, // Token + NULL, // Host + DumpData // PrecGauge + ); + continue; + } + + pBS->SetMem (&PerfData, sizeof (EFI_PERF_DATA), 0); + + //convert CHAR16 string to CHAR8 string + Src = DumpData->Token; + Dest = (UINT8 *) PerfData.Token; + while (*Src) *Dest++ = (UINT8) (*Src++); + *Dest = 0; + + PerfData.Duration = (UINT32) Div64 ( + DumpData->EndTick - DumpData->StartTick, + (UINT32) Freq, + NULL + ); + + pBS->CopyMem(Ptr, &PerfData, sizeof (EFI_PERF_DATA)); + Ptr += sizeof (EFI_PERF_DATA); + + PerfHeader.Count++; + if (PerfHeader.Count == LimitCount) { + goto Done; + } + + DumpData = DrvPerf->GetGauge ( + DrvPerf, // Context + NULL, // Handle + NULL, // Token + NULL, // Host + DumpData // PrecGauge + ); + } + +Done: + PerfHeader.Signiture = 0x66726550; + + // Put performance data to memory + pBS->CopyMem ( + (UINTN *) (UINTN) AcpiLowMemoryBase, + &PerfHeader, + sizeof (EFI_PERF_HEADER) + ); + + if(FirstCall) + { + pRS->SetVariable ( + L"PerfDataMemAddrInternal", + &gAmiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (UINT32), + (VOID *) &AcpiLowMemoryBase); + + Status = pRS->SetVariable ( + L"PerfDataMemAddr", + &gAmiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof (UINT32), + (VOID *) &AcpiLowMemoryBase); + + + TRACE((-1, "Setting PerfDataMemAddr Var. Status = %r",Status)); + if (EFI_ERROR (Status)) return; + FirstCall = FALSE; + + } +} + +static EFI_FPDT_STRUCTURE *FpdtVar = NULL; +//************************************************************************* +// +// +// Name: AmiFillFpdt +// +// Description: +// VOID AmiFillFpdt () Finds address of Bas Boot Perf Record and +// writes performance data into it, based on inpoot parameter. +// +// Input: +// FPDT_FILL_TYPE FieldToFill - Indicator which field in Bas Boot Perf Record to fill +// +// Output: +// VOID. +// +// +//************************************************************************* +VOID AmiFillFpdt (IN FPDT_FILL_TYPE FieldToFill){ + BASIC_BOOT_PERF_REC *BasBootPerRec; + EFI_STATUS StatusFpdt; + UINTN VarSize = sizeof(UINT32); + + if ((FpdtVar == NULL) || (FpdtVar->NanoFreq == 0) || (FpdtVar->BasBootPointer == 0)){ + StatusFpdt = pRS->GetVariable( + EFI_FPDT_VARIABLE, &gAmiGlobalVariableGuid, + NULL, &VarSize, &FpdtVar + ); + if (EFI_ERROR (StatusFpdt) || (FpdtVar->NanoFreq == 0) || (FpdtVar->BasBootPointer == 0)) + return; + } + if (((PERF_TAB_HEADER*)(UINT8*)(FpdtVar->BasBootPointer))->Signature != 0x54504246) + return; + BasBootPerRec = (BASIC_BOOT_PERF_REC*)((UINT8*)(FpdtVar->BasBootPointer) + sizeof(PERF_TAB_HEADER)); + if (BasBootPerRec->Header.PerfRecType != 2) return; + switch (FieldToFill) + { + case FillOsLoaderLoadImageStart: + + BasBootPerRec->OsLoaderLoadImageStart = Div64 (Mul64 (GetCpuTimer (), (UINTN)FpdtVar->NanoFreq), 1000000 , NULL); + break; + + case FillOsLoaderStartImageStart: + + BasBootPerRec->OsLoaderStartImageStart = Div64 (Mul64 (GetCpuTimer (), (UINTN)FpdtVar->NanoFreq), 1000000 , NULL); + break; + + case FillExitBootServicesEntry: + + BasBootPerRec->ExitBootServicesEntry = Div64 (Mul64 (GetCpuTimer (), (UINTN)FpdtVar->NanoFreq), 1000000 , NULL); + break; + + case FillExitBootServicesExit: + + BasBootPerRec->ExitBootServicesExit = Div64 (Mul64 (GetCpuTimer (), (UINTN)FpdtVar->NanoFreq), 1000000 , NULL); + break; + + } + +} + + + + +static INT32 NumberOfGoVirtualCallbacks=0; +static INT32 NumberOfExitBsCallbacks=0; +static EFI_RUNTIME_SERVICES *LibTempCopyOfpRs=NULL; + +static VOID AmiLibExitBs (IN EFI_EVENT Event, IN VOID *Context){ + IsAtRuntime=TRUE; + if (Context!=NULL) ((EFI_EVENT_NOTIFY)Context)(Event,NULL); + if (--NumberOfExitBsCallbacks==0){ + pBS = NULL; + LibTempCopyOfpRs = pRS; + } +} +static VOID AmiLibGoVirtual (IN EFI_EVENT Event, IN VOID *Context){ + IsInVirtualMode=TRUE; + if (Context!=NULL) ((EFI_EVENT_NOTIFY)Context)(Event,NULL); + if (--NumberOfGoVirtualCallbacks==0){ + // at this point it is not safe to use pRS + // because it may have been already converted to the virtual address + // by the library consumer. + LibTempCopyOfpRs->ConvertPointer(0,&pST); + LibTempCopyOfpRs->ConvertPointer(0,&pRS); + if (StatusCodePtr != NULL) LibTempCopyOfpRs->ConvertPointer(0,&StatusCodePtr); + } +} + +//************************************************************************* +// +// +// Name: InitAmiRuntimeLib +// +// Description: +// VOID InitAmiRuntimeLib(IN EFI_HANDLE ImageHandle, +// IN EFI_SYSTEM_TABLE *SystemTable, IN EFI_EVENT_NOTIFY ExitBsCallback OPTIONAL, +// IN EFI_EVENT_NOTIFY GoVirtualCallback OPTIONAL) initializes the global variables using call to InitAmiLib. +// Runtime drivers should use this function instead of InitAmiLib. +// +// Input: +// IN EFI_HANDLE ImageHandle +// The image handle. +// +// IN EFI_SYSTEM_TABLE *SystemTable +// Pointer to the EFI System Table. +// +// IN EFI_EVENT_NOTIFY ExitBsCallback OPTIONAL +// Optional Exit Boot Services callback function pointer +// +// IN EFI_EVENT_NOTIFY GoVirtualCallback OPTIONAL +// Optional Virtual Address Change callback function pointer +// +// Output: +// VOID. +// +// Modified: +// pST +// pBS +// pRS +// TheImageHandle +// +// Referrals: +// +// Notes: +// The global variables initialized by this function are: +// pST Pointer to the EFI System Table. +// pBS Pointer to the Boot Services Table. +// pRS Pointer to the Runtime Services Table. +// TheImageHandle Image handle. +// +// +//************************************************************************* +VOID EFIAPI InitAmiRuntimeLib( + IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable, + IN EFI_EVENT_NOTIFY ExitBsCallback OPTIONAL, + IN EFI_EVENT_NOTIFY GoVirtualCallback OPTIONAL +){ + EFI_EVENT Event; + InitAmiLib(ImageHandle,SystemTable); + LibInitStatusCodePtr(); + NumberOfExitBsCallbacks++; + NumberOfGoVirtualCallbacks++; + pBS->CreateEvent( + EVT_SIGNAL_EXIT_BOOT_SERVICES,TPL_CALLBACK, + &AmiLibExitBs, ExitBsCallback, &Event + ); + pBS->CreateEvent( + EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,TPL_CALLBACK, + &AmiLibGoVirtual, GoVirtualCallback, &Event + ); +} + +//************************************************************************* +// +// +// Name: EfiAtRuntime +// +// Description: +// BOOLEAN EFIAPI EfiAtRuntime ( VOID ) returns TRUE if system has already +// transitioned to runtime(ExitBootServices has been called), otherwise returns FALSE. +// This function can only be used is driver has been initialized using InitAmiRuntimeLib function. +// +// Input: +// None +// +// Output: +// BOOLEAN TRUE - system is in UEFI Runtime. +// FALSE - system is in the boot time. +// +// Referrals: +// InitAmiRuntimeLib +// +// Notes: +// This function can only be used if driver has been initialized using InitAmiRuntimeLib function. +// This function does not detect legacy boot. +// It will keep returning FALSE if called after the boot to legacy OS. +// +// +//************************************************************************* +BOOLEAN EFIAPI EfiAtRuntime ( VOID ) {return IsAtRuntime;} + +//************************************************************************* +// +// +// Name: EfiGoneVirtual +// +// Description: +// BOOLEAN EFIAPI EfiGoneVirtual ( VOID ) returns TRUE if system has already +// transitioned to the virtual addressing mode (SetVirtualAddressMap has been called), otherwise returns FALSE. +// This function can only be used is driver has been initialized using InitAmiRuntimeLib function. +// +// Input: +// None +// +// Output: +// BOOLEAN TRUE - system is in virtual addressing mode. +// FALSE - system is not in virtual addressing mode. +// +// Referrals: +// InitAmiRuntimeLib +// +// Notes: +// This function can only be used if driver has been initialized using InitAmiRuntimeLib function. +// +// +//************************************************************************* +BOOLEAN EFIAPI EfiGoneVirtual ( VOID ) {return IsInVirtualMode;} + +//************************************************************************* +// +// +// Name: StrcmpNoCase +// +// Description: +// Function compares two CHAR8 strings ignoring case for letters +// +// Input: +// CHAR8 *Str1 - pointer to first string +// CHAR8 *Str2 - pointer to second string +// +// Output: +// BOOLEAN TRUE - strings are equal (en-us is equal to en-US) +// FALSE - strings are not equal +// +// Referrals: +// None +// +// +//************************************************************************* +BOOLEAN StrcmpNoCase(CHAR8 *Str1, CHAR8 *Str2) +{ + CHAR8 Char1; + CHAR8 Char2; + while (*Str1) { + if(*Str1 != *Str2) { + Char1 = (*Str1 >= 0x41 && *Str1 <= 0x5a) ? *Str1 : (*Str1 >= 0x61 && *Str1 <= 0x7a) ? *Str1 - 0x20 : 0xff; + Char2 = (*Str2 >= 0x41 && *Str2 <= 0x5a) ? *Str2 : (*Str2 >= 0x61 && *Str2 <= 0x7a) ? *Str2 - 0x20 : 0; + if(Char1 != Char2) + return FALSE; + } + Str1++; + Str2++; + } + return (*Str1 == *Str2); +} + +//************************************************************************* +// +// +// Name: LanguageCodesEqual +// +// Description: +// BOOLEAN LanguageCodesEqual(CONST CHAR8* LangCode1, CONST CHAR8* LangCode2) +// compares two language codes and returns TRUE if they are equal. +// Case is ignored (RFC 4646 requirement) +// +// Input: +// CONST CHAR8* LangCode1 - first language code +// CONST CHAR8* LangCode2 - second language code +// +// Output: +// BOOLEAN TRUE - the language codes are equal +// FALSE - the language codes are not equal +// +// Notes: +// if EFI_SPECIFICATION_VERSION is greater than 0x00020000, the function +// expects language codes in RFC 4646 format. +// if EFI_SPECIFICATION_VERSION is less or equal than 0x00020000, the function +// expects language codes in ISO 639-2 format. +// +// +//************************************************************************* +BOOLEAN LanguageCodesEqual(CONST CHAR8* LangCode1, CONST CHAR8* LangCode2) { + return +#if EFI_SPECIFICATION_VERSION<=0x20000 + LangCode1[0]==LangCode2[0] + && LangCode1[1]==LangCode2[1] + && LangCode1[2]==LangCode2[2]; +#else + StrcmpNoCase((CHAR8*)LangCode1, (CHAR8*)LangCode2); +#endif +} + +VOID* _GetBootScriptSaveInterface(){ + static VOID* BootScriptSaveInterface = NULL; + static EFI_GUID gEfiBootScriptSaveInterfaceGuid = EFI_BOOT_SCRIPT_SAVE_GUID; + EFI_STATUS Status; + + if (BootScriptSaveInterface != NULL) return BootScriptSaveInterface; + ASSERT(pBS!=NULL) + Status = pBS->LocateProtocol( + &gEfiBootScriptSaveInterfaceGuid,NULL,&BootScriptSaveInterface + ); + if (EFI_ERROR(Status)) BootScriptSaveInterface = NULL; + return BootScriptSaveInterface; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2012, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Library/IO.c b/Library/IO.c new file mode 100644 index 0000000..532ff94 --- /dev/null +++ b/Library/IO.c @@ -0,0 +1,664 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//************************************************************************* +// $Header: /Alaska/SOURCE/Core/Library/IO.c 4 7/10/09 3:49p Felixp $ +// +// $Revision: 4 $ +// +// $Date: 7/10/09 3:49p $ +//************************************************************************* +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/Library/IO.c $ +// +// 4 7/10/09 3:49p Felixp +// Function headers added +// +// 3 8/24/06 9:26a Felixp +// Preliminary x64 support (work in progress): +// 1. Processor architecture specific functions moved to a processor +// library +// 2. Makefile removed (AmiLib files are build by the AmiPeiLib and +// AmeDxeLib makefile) +// 3. Tokens.c added +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 12/23/04 9:42a Felixp +// +// 7 4/09/04 12:47p Markw +// Fixed IoWrites. +// +// 6 3/23/04 4:56p Felixp +// +// 5 3/08/04 5:44p Markw +// +// +// 4 3/05/04 5:48p Markw +// Added IoRead, IoWrite, IoRead, MemRead, MemWrite, MemReadWrite to +// support BootScript. +// +// 3 2/20/04 11:37a Felixp +// read functions simplified (return value passed via eax) +// +// 2 2/19/04 1:27p Markw +// Added include +// +// 1 2/19/04 12:54p Markw +// +//************************************************************************* +// +// +// Name: IO.c +// +// Description: +// Contains generic I/O read/write functions. +// +// +//************************************************************************* +#include + +//************************************************************************* +// +// +// Name: IO_Read_Write_Functions +// +// Description: +// Generic I/O read/write functions. +// +// Fields: Header Function Description +// ------------------------------------------------------------------ +// AmiLib IoRead Read value(s) from an I/O address or an entire region. +// AmiLib IoRead8 Read 8-bit value from an I/O address. +// AmiLib IoRead16 Read 16-bit value from an I/O address. +// AmiLib IoRead32 Read 32-bit value from an I/O address. +// AmiLib IoReadWrite Read value from an I/O address then write back a value. +// AmiLib IoWrite Write buffer to an I/O address or region. +// AmiLib IoWrite8 Write 8-bit value to an I/O address. +// AmiLib IoWrite16 Write 16-bit value to an I/O address. +// AmiLib IoWrite32 Write 32-bit value to an I/O address. +// AmiLib MemRead Read value(s) from a memory mapped I/O address or an entire region. +// AmiLib MemReadWrite Read value from a memory mapped I/O address then write back a value. +// AmiLib MemWrite Write buffer to an I/O address or region. +// +// Notes: +// Header details which header file contains the function prototype for +// the above functions. Append .h to the given name. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: IoRead +// +// Description: +// EFI_STATUS IoRead(IN CPU_IO_WIDTH Width, IN UINT64 Address, +// IN UINTN Count, OUT VOID *Buffer) performs Count I/O reads of the defined +// Width at the Address and stores the result in Buffer. After every I/O +// operation, Address and Buffer are updated according to the Width. See +// notes for details. +// +// Input: +// IN CPU_IO_WIDTH Width +// Number of bits to read from I/O. Supports at most 32-bits. +// +// IN UINT64 Address +// I/O address to read from. +// +// IN UINTN Count +// Number of reads to perform. +// +// OUT VOID *Buffer +// Buffer where the read results will be stored. User is responsible for +// properly allocating the necessary memory resources. +// +// Output: +// EFI_INVALID_PARAMETER, if Count = 0, Width > 32-bits, or the range of +// Address > 0xffff. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// IoRead8 +// IoRead16 +// IoRead32 +// +// Notes: +// Address and Buffer are updated according to the Width as follows: +// CpuIoWidthUint8 - Both Address and Buffer are incremented by 1. +// CpuIoWidthUint16 - Both Address and Buffer are incremented by 2. +// CpuIoWidthUint32 - Both Address and Buffer are incremented by 4. +// CpuIoWidthFifoUint8 - Only Buffer is incremented by 1. +// CpuIoWidthFifoUint16 - Only Buffer is incremented by 2. +// CpuIoWidthFifoUint32 - Only Buffer is incremented by 4. +// CpuIoWidthFillUint8 - Only Address is incremented by 1. +// CpuIoWidthFillUint16 - Only Address is incremented by 2. +// CpuIoWidthFillUint32 - Only Address is incremented by 4. +// +// +//************************************************************************* +EFI_STATUS IoRead( + IN CPU_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + UINT8 ValueWidth = 1 << (Width & 3); + UINT8 AddrInc, BuffInc; + UINTN AddrCount; + + AddrInc = BuffInc = ValueWidth; + + switch (Width & ~3) + { + case CpuIoWidthFifoUint8: AddrInc = 0; break; + case CpuIoWidthFillUint8: BuffInc = 0; break; + } + + AddrCount = (Count-1) * AddrInc + ValueWidth; + + + //---Validate Inputs--- + if (!Count) return EFI_INVALID_PARAMETER; + if (Address + AddrCount > 0xffff) return EFI_INVALID_PARAMETER; + if ((Width & 3) > CpuIoWidthUint32) return EFI_INVALID_PARAMETER; + + + while (Count--) + { + switch(Width & 3) + { + case CpuIoWidthUint8: + *(UINT8*)Buffer = IoRead8((UINT16)Address); + break; + case CpuIoWidthUint16: + *(UINT16*)Buffer = IoRead16((UINT16)Address); + break; + default: + *(UINT32*)Buffer = IoRead32((UINT16)Address); + } + Address = Address + AddrInc; + Buffer = (UINT8*) Buffer + BuffInc; + } + + return EFI_SUCCESS; +} + +//************************************************************************* +// +// +// Name: IoWrite +// +// Description: +// EFI_STATUS IoWrite(IN CPU_IO_WIDTH Width, IN UINT64 Address, +// IN UINTN Count, IN VOID *Buffer) performs Count I/O writes of the defined +// Width at the Address from the Buffer. After every I/O operation, Address +// and Buffer are updated according to the Width. See notes for details. +// +// Input: +// IN CPU_IO_WIDTH Width +// Number of bits to read from I/O. Supports at most 32-bits. +// +// IN UINT64 Address +// I/O address to write to. +// +// IN UINTN Count +// Number of writes to perform. +// +// IN VOID *Buffer +// Buffer where the data to be written is located. +// +// Output: +// EFI_INVALID_PARAMETER, if Count = 0, Width > 32-bits, or the range of +// Address > 0xffff. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// IoWrite8 +// IoWrite16 +// IoWrite32 +// +// Notes: +// Address and Buffer are updated according to the Width as follows: +// CpuIoWidthUint8 - Both Address and Buffer are incremented by 1. +// CpuIoWidthUint16 - Both Address and Buffer are incremented by 2. +// CpuIoWidthUint32 - Both Address and Buffer are incremented by 4. +// CpuIoWidthFifoUint8 - Only Buffer is incremented by 1. +// CpuIoWidthFifoUint16 - Only Buffer is incremented by 2. +// CpuIoWidthFifoUint32 - Only Buffer is incremented by 4. +// CpuIoWidthFillUint8 - Only Address is incremented by 1. +// CpuIoWidthFillUint16 - Only Address is incremented by 2. +// CpuIoWidthFillUint32 - Only Address is incremented by 4. +// +// +//************************************************************************* +EFI_STATUS IoWrite( + IN CPU_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + UINT8 ValueWidth = 1 << (Width & 3); + UINT8 AddrInc, BuffInc; + UINTN AddrCount; + + AddrInc = BuffInc = ValueWidth; + + switch (Width & ~3) + { + case CpuIoWidthFifoUint8: AddrInc = 0; break; + case CpuIoWidthFillUint8: BuffInc = 0; break; + } + + AddrCount = (Count-1) * AddrInc + ValueWidth; + + + //---Validate Inputs--- + if (!Count) return EFI_INVALID_PARAMETER; + if (Address + AddrCount > 0xffff) return EFI_INVALID_PARAMETER; + if ((Width & 3) > CpuIoWidthUint32) return EFI_INVALID_PARAMETER; + + + while (Count--) + { + switch(Width & 3) + { + case CpuIoWidthUint8: + IoWrite8((UINT16)Address, *(UINT8*) Buffer); + break; + case CpuIoWidthUint16: + IoWrite16((UINT16)Address, *(UINT16*) Buffer); + break; + default: + IoWrite32((UINT16)Address, *(UINT32*) Buffer); + } + Address = Address + AddrInc; + Buffer = (UINT8*) Buffer + BuffInc; + } + + return EFI_SUCCESS; +} + +//************************************************************************* +// +// +// Name: IoReadWrite +// +// Description: +// EFI_STATUS IoReadWrite(IN CPU_IO_WIDTH Width, IN UINT64 Address, +// IN VOID *DataValue, IN VOID *DataMask) reads the specified I/O Address, +// ANDs the result with DataMask, then ORs the modified result with DataValue +// and writes the value back to Address. +// +// Input: +// IN CPU_IO_WIDTH Width +// Number of bits to read/write from I/O. Only supports: CpuIoWidthUint8, +// CpuIoWidthUint16, and CpuIoWidthUint32. +// +// IN UINT64 Address +// I/O address to read and write to. +// +// IN VOID *DataValue +// UINT32 OR mask value. +// +// IN VOID *DataMask +// UINT32 AND mask value. +// +// Output: +// EFI_INVALID_PARAMETER, if Width not supported, or the range of +// Address > 0xffff. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// IoWrite +// IoRead +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS IoReadWrite( + IN CPU_IO_WIDTH Width, + IN UINT64 Address, + IN VOID *DataValue, + IN VOID *DataMask + ) +{ + EFI_STATUS Status; + UINT32 Value32; + UINT32 Mask; + UINT32 Data; + +#if defined(EFI64) || defined(EFIx64) + //In case of aligment issues. + Mask = *((UINT8*)DataMask + 3) + *((UINT8*)DataMask + 2) + *((UINT8*)DataMask + 1) + *(UINT8*)DataMask; + Data = *((UINT8*)DataValue + 3) + *((UINT8*)DataValue + 2) + *((UINT8*)DataValue + 1) + *(UINT8*)DataValue; + ///////////////////////////// +#else + Mask = *(UINT32*)DataMask; + Data = *(UINT32*)DataValue; +#endif + + if ((Width & ~3) != CpuIoWidthUint8) return EFI_INVALID_PARAMETER; //Only CpuIoWidthUintxx Supported + + + if ((Status = IoRead(Width, Address, 1, &Value32) != EFI_SUCCESS)) return Status; + Value32 &= Mask; + Value32 |= Data; + return IoWrite(Width,Address,1,&Value32); +} + +//************************************************************************* +// +// +// Name: MemRead +// +// Description: +// EFI_STATUS MemRead(IN CPU_IO_WIDTH Width, IN UINT64 Address, +// IN UINTN Count, IN VOID *Buffer) performs Count MMIO reads of the size +// Width at the Address and stores the result in Buffer. After every MMIO +// operation, Address and Buffer are updated according to Width. +// +// Input: +// IN CPU_IO_WIDTH Width +// The width of the access. +// +// IN UINT64 Address +// The physical address of the access. +// +// IN UINTN Count +// The number of accesses to perform. +// +// IN VOID *Buffer +// A pointer to the buffer of data. User is responsible for allocating the +// necessary memory resources. +// +// Output: +// EFI_INVALID_PARAMETER, if Count = 0, Width not supported, or the range of +// Address overflows the bounds of memory. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// +// Notes: +// Address and Buffer are updated according to Width as follows: +// CpuIoWidthUint8 - Both Address and Buffer are incremented by 1. +// CpuIoWidthUint16 - Both Address and Buffer are incremented by 2. +// CpuIoWidthUint32 - Both Address and Buffer are incremented by 4. +// CpuIoWidthUint64 - Both Address and Buffer are incremented by 8. +// CpuIoWidthFifoUint8 - Only Buffer is incremented by 1. +// CpuIoWidthFifoUint16 - Only Buffer is incremented by 2. +// CpuIoWidthFifoUint32 - Only Buffer is incremented by 4. +// CpuIoWidthFifoUint64 - Only Buffer is incremented by 8. +// CpuIoWidthFillUint8 - Only Address is incremented by 1. +// CpuIoWidthFillUint16 - Only Address is incremented by 2. +// CpuIoWidthFillUint32 - Only Address is incremented by 4. +// CpuIoWidthFillUint64 - Only Address is incremented by 8. +// +// +//************************************************************************* +EFI_STATUS MemRead( + IN CPU_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + UINT8 ValueWidth = 1 << (Width & 3); + UINT8 AddrInc, BuffInc; + UINTN AddrCount; + + AddrInc = BuffInc = ValueWidth; + + switch (Width & ~3) + { + case CpuIoWidthFifoUint8: AddrInc = 0; break; + case CpuIoWidthFillUint8: BuffInc = 0; break; + } + + AddrCount = (Count-1) * AddrInc + ValueWidth; + + //---Validate Inputs--- + if (!Count) return EFI_INVALID_PARAMETER; + +#if defined(EFI64) || defined(EFIx64) + if (Address + AddrCount < Address) return EFI_INVALID_PARAMETER; //Overflow +#else + if (Address + AddrCount > 0xffffffff) return EFI_INVALID_PARAMETER; + if ((Width & 3) > CpuIoWidthUint32) return EFI_INVALID_PARAMETER; +#endif + + + while (Count--) + { + switch(Width & 3) + { + case CpuIoWidthUint8: + *(UINT8*)Buffer = *(UINT8*)Address; + break; + case CpuIoWidthUint16: + *(UINT16*)Buffer = *(UINT16*)Address; + break; + case CpuIoWidthUint32: + *(UINT32*)Buffer = *(UINT32*)Address; + break; + default: + *(UINT64*)Buffer = *(UINT64*)Address; + } + Address = Address + AddrInc; + Buffer = (UINT8*) Buffer + BuffInc; + } + + return EFI_SUCCESS; +} + +//************************************************************************* +// +// +// Name: MemWrite +// +// Description: +// EFI_STATUS MemWrite(IN CPU_IO_WIDTH Width, IN UINT64 Address, +// IN UINTN Count, OUT VOID *Buffer) performs Count MMIO writes of the size +// Width at the Address using the contents of Buffer. After every MMIO +// operation, Address and Buffer are updated according to Width. +// +// Input: +// IN CPU_IO_WIDTH Width +// The width of the access. +// +// IN UINT64 Address +// The physical address of the access. +// +// IN UINTN Count +// The number of accesses to perform. +// +// OUT VOID *Buffer +// A pointer to the buffer of data. +// +// Output: +// EFI_INVALID_PARAMETER, if Count = 0, Width not supported, or the range of +// Address overflows the bounds of memory. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// +// Notes: +// Address and Buffer are updated according to Width as follows: +// CpuIoWidthUint8 - Both Address and Buffer are incremented by 1. +// CpuIoWidthUint16 - Both Address and Buffer are incremented by 2. +// CpuIoWidthUint32 - Both Address and Buffer are incremented by 4. +// CpuIoWidthUint64 - Both Address and Buffer are incremented by 8. +// CpuIoWidthFifoUint8 - Only Buffer is incremented by 1. +// CpuIoWidthFifoUint16 - Only Buffer is incremented by 2. +// CpuIoWidthFifoUint32 - Only Buffer is incremented by 4. +// CpuIoWidthFifoUint64 - Only Buffer is incremented by 8. +// CpuIoWidthFillUint8 - Only Address is incremented by 1. +// CpuIoWidthFillUint16 - Only Address is incremented by 2. +// CpuIoWidthFillUint32 - Only Address is incremented by 4. +// CpuIoWidthFillUint64 - Only Address is incremented by 8. +// +// +//************************************************************************* +EFI_STATUS MemWrite( + IN CPU_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + UINT8 ValueWidth = 1 << (Width & 3); + UINT8 AddrInc, BuffInc; + UINTN AddrCount; + + AddrInc = BuffInc = ValueWidth; + + switch (Width & ~3) + { + case CpuIoWidthFifoUint8: AddrInc = 0; break; + case CpuIoWidthFillUint8: BuffInc = 0; break; + } + + AddrCount = (Count-1) * AddrInc + ValueWidth; + + //---Validate Inputs--- + if (!Count) return EFI_INVALID_PARAMETER; + +#if defined(EFI64) || defined(EFIx64) + if (Address + AddrCount < Address) return EFI_INVALID_PARAMETER; //Overflow +#else + if (Address + AddrCount > 0xffffffff) return EFI_INVALID_PARAMETER; + if ((Width & 3) > CpuIoWidthUint32) return EFI_INVALID_PARAMETER; +#endif + + + while (Count--) + { + switch(Width & 3) + { + case CpuIoWidthUint8: + *(UINT8*)Address = *(UINT8*)Buffer; + break; + case CpuIoWidthUint16: + *(UINT16*)Address = *(UINT16*)Buffer; + break; + case CpuIoWidthUint32: + *(UINT32*)Address = *(UINT32*) Buffer; + break; + default: + *(UINT64*)Address = *(UINT64*) Buffer; + } + Address = Address + AddrInc; + Buffer = (UINT8*) Buffer + BuffInc; + } + + return EFI_SUCCESS; +} + +//************************************************************************* +// +// +// Name: MemReadWrite +// +// Description: +// EFI_STATUS MemReadWrite(IN CPU_IO_WIDTH Width, IN UINT64 Address, +// IN VOID *DataValue, IN VOID *DataMask) reads the specified physical +// Address, ANDs the result with DataMask, then ORs the modified result with +// DataValue and writes the value back to Address. +// +// Input: +// IN CPU_IO_WIDTH Width +// The width of the access. Only supports CpuIoWidthUintxx. +// +// IN UINT64 Address +// The physical address of the access. +// +// IN VOID *DataValue +// UINT64 OR mask value. +// +// IN VOID *DataMask +// UINT64 AND mask value. +// +// Output: +// EFI_INVALID_PARAMETER, if Width not supported, or the range of +// Address overflows the bounds of memory. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS MemReadWrite( + IN CPU_IO_WIDTH Width, + IN UINT64 Address, + IN VOID *DataValue, + IN VOID *DataMask + ) +{ + EFI_STATUS Status; + UINT64 Value64; + UINT64 Mask; + UINT64 Data; + +#if defined(EFI64) || defined(EFIx64) + //In case of aligment issues. + Mask = *((UINT8*)DataMask + 4) + *((UINT8*)DataMask + 3) + *((UINT8*)DataMask + 2) + *((UINT8*)DataMask + 1) + *(UINT8*)DataMask; + Data = *((UINT8*)DataValue + 4) + *((UINT8*)DataValue + 3) + *((UINT8*)DataValue + 2) + *((UINT8*)DataValue + 1) + *(UINT8*)DataValue; + ///////////////////////////// +#else + Mask = *(UINT64*)DataMask; + Data = *(UINT64*)DataValue; +#endif + + if ((Width & ~3) != CpuIoWidthUint8) return EFI_INVALID_PARAMETER; //Only CpuIoWidthUintxx Supported + + if ((Status = MemRead(Width, Address, 1, &Value64) != EFI_SUCCESS)) return Status; + Value64 &= Mask; + Value64 |= Data; + return MemWrite(Width,Address,1,&Value64); +} + + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Library/LibSrc.cif b/Library/LibSrc.cif new file mode 100644 index 0000000..78a93db --- /dev/null +++ b/Library/LibSrc.cif @@ -0,0 +1,14 @@ + + name = "Library Sources" + category = ModulePart + LocalRoot = "Library\" + RefName = "LibSrc" +[files] +"LibSrc.sdl" +[parts] +"AmiLib" +"AmiPeiLib" +"AmiDxeLib" +"AmiIa32Lib" +"AmiX64Lib" + diff --git a/Library/LibSrc.sdl b/Library/LibSrc.sdl new file mode 100644 index 0000000..a99bc22 --- /dev/null +++ b/Library/LibSrc.sdl @@ -0,0 +1,10 @@ +TOKEN + Name = "LibSrc_SUPPORT" + Value = "1" + Help = "Main switch to enable Library Sources support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + diff --git a/Library/Library.cif b/Library/Library.cif new file mode 100644 index 0000000..5909989 --- /dev/null +++ b/Library/Library.cif @@ -0,0 +1,10 @@ + + name = "Library" + category = ModulePart + LocalRoot = "Library\" + RefName = "Library" +[files] +"Library.sdl" +"Tokens.c" +"AmiLib.chm" + diff --git a/Library/Library.sdl b/Library/Library.sdl new file mode 100644 index 0000000..f3a4a83 --- /dev/null +++ b/Library/Library.sdl @@ -0,0 +1,36 @@ +TOKEN + Name = "Library_SUPPORT" + Value = "1" + Help = "Main switch to enable Library support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "LIBRARY_DIR" +End + +ELINK + Name = "AMIPEILIB" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "$(LIBRARY_DIR)\AmiPeiLib$(ARCH)$(DBG).lib" + Parent = "AMIPEILIB" + InvokeOrder = AfterParent +End + +ELINK + Name = "AMIDXELIB" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "$(LIBRARY_DIR)\AmiDxeLib$(ARCH)$(DBG).lib" + Parent = "AMIDXELIB" + InvokeOrder = AfterParent +End + diff --git a/Library/LinkedList.c b/Library/LinkedList.c new file mode 100644 index 0000000..589308f --- /dev/null +++ b/Library/LinkedList.c @@ -0,0 +1,355 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + LinkedList.c + +Abstract: + + Linked List Library Functions + +--*/ + +#include + + +VOID +InitializeListHead ( + EFI_LIST_ENTRY *List + ) +/*++ + +Routine Description: + + Initialize the head of the List. The caller must allocate the memory + for the EFI_LIST. This function must be called before the other linked + list macros can be used. + +Arguments: + + List - Pointer to list head to initialize + +Returns: + + None. + +--*/ + +{ + List->ForwardLink = List; + List->BackLink = List; +} + + +BOOLEAN +IsListEmpty ( + EFI_LIST_ENTRY *List + ) +/*++ + +Routine Description: + + Return TRUE is the list contains zero nodes. Otherzise return FALSE. + The list must have been initialized with InitializeListHead () before using + this function. + +Arguments: + + List - Pointer to list head to test + + +Returns: + + Return TRUE is the list contains zero nodes. Otherzise return FALSE. + +--*/ +{ + return (BOOLEAN)(List->ForwardLink == List); +} + + +VOID +RemoveEntryList ( + EFI_LIST_ENTRY *Entry + ) +/*++ + +Routine Description: + + Remove Node from the doubly linked list. It is the caller's responsibility + to free any memory used by the entry if needed. The list must have been + initialized with InitializeListHead () before using this function. + +Arguments: + + Entry - Element to remove from the list. + +Returns: + + None + +--*/ +{ + EFI_LIST_ENTRY *_ForwardLink; + EFI_LIST_ENTRY *_BackLink; + + _ForwardLink = Entry->ForwardLink; + _BackLink = Entry->BackLink; + _BackLink->ForwardLink = _ForwardLink; + _ForwardLink->BackLink = _BackLink; + +#if EFI_DEBUG + Entry->ForwardLink = (EFI_LIST_ENTRY *) 0xAFAFAFAF; + Entry->BackLink = (EFI_LIST_ENTRY *) 0xAFAFAFAF; +#endif +} + + +VOID +InsertTailList ( + EFI_LIST_ENTRY *ListHead, + EFI_LIST_ENTRY *Entry + ) +/*++ + +Routine Description: + + Insert a Node into the end of a doubly linked list. The list must have + been initialized with InitializeListHead () before using this function. + +Arguments: + + ListHead - Head of doubly linked list + + Entry - Element to insert at the end of the list. + +Returns: + + None + +--*/ +{ + EFI_LIST_ENTRY *_ListHead; + EFI_LIST_ENTRY *_BackLink; + + _ListHead = ListHead; + _BackLink = _ListHead->BackLink; + Entry->ForwardLink = _ListHead; + Entry->BackLink = _BackLink; + _BackLink->ForwardLink = Entry; + _ListHead->BackLink = Entry; +} + + + +VOID +InsertHeadList ( + EFI_LIST_ENTRY *ListHead, + EFI_LIST_ENTRY *Entry + ) +/*++ + +Routine Description: + + Insert a Node into the start of a doubly linked list. The list must have + been initialized with InitializeListHead () before using this function. + +Arguments: + + ListHead - Head of doubly linked list + + Entry - Element to insert to beginning of list + +Returns: + + None + +--*/ +{ + EFI_LIST_ENTRY *_ListHead; + EFI_LIST_ENTRY *_ForwardLink; + + _ListHead = ListHead; + _ForwardLink = _ListHead->ForwardLink; + Entry->ForwardLink = _ForwardLink; + Entry->BackLink = _ListHead; + _ForwardLink->BackLink = Entry; + _ListHead->ForwardLink = Entry; +} + +VOID +SwapListEntries ( + EFI_LIST_ENTRY *Entry1, + EFI_LIST_ENTRY *Entry2 + ) +/*++ + +Routine Description: + + Swap the location of the two elements of a doubly linked list. Node2 + is placed in front of Node1. The list must have been initialized with + InitializeListHead () before using this function. + +Arguments: + + Entry1 - Element in the doubly linked list in front of Node2. + + Entry2 - Element in the doubly linked list behind Node1. + +Returns: + + None + +--*/ +{ + EFI_LIST_ENTRY *Entry1ForwardLink; + EFI_LIST_ENTRY *Entry1BackLink; + EFI_LIST_ENTRY *Entry2ForwardLink; + EFI_LIST_ENTRY *Entry2BackLink; + + Entry2ForwardLink = Entry2->ForwardLink; + Entry2BackLink = Entry2->BackLink; + Entry1ForwardLink = Entry1->ForwardLink; + Entry1BackLink = Entry1->BackLink; + Entry2BackLink->ForwardLink = Entry2ForwardLink; + Entry2ForwardLink->BackLink = Entry2BackLink; + Entry2->ForwardLink = Entry1; + Entry2->BackLink = Entry1BackLink; + Entry1BackLink->ForwardLink = Entry2; + Entry1->BackLink = Entry2; +} + + +EFI_LIST_ENTRY * +GetFirstNode ( + EFI_LIST_ENTRY *List + ) +/*++ + +Routine Description: + + Return the first node pointed to by the list head. The list must + have been initialized with InitializeListHead () before using this + function and must contain data. + +Arguments: + + List - The head of the doubly linked list. + +Returns: + + Pointer to the first node, if the list contains nodes. The list will + return a null value--that is, the value of List--when the list is empty. + See the description of IsNull for more information. + + +--*/ +{ + return List->ForwardLink; +} + + +EFI_LIST_ENTRY * +GetNextNode ( + EFI_LIST_ENTRY *List, + EFI_LIST_ENTRY *Node + ) +/*++ + +Routine Description: + + Returns the node following Node in the list. The list must + have been initialized with InitializeListHead () before using this + function and must contain data. + +Arguments: + + List - The head of the list. MUST NOT be the literal value NULL. + Node - The node in the list. This value MUST NOT be the literal value NULL. + See the description of IsNull for more information. + +Returns: + + Pointer to the next node, if one exists. Otherwise, returns a null value, + which is actually a pointer to List. + See the description of IsNull for more information. + +--*/ +{ + if (Node == List) { + return List; + } + return Node->ForwardLink; +} + + +BOOLEAN +IsNull ( + EFI_LIST_ENTRY *List, + EFI_LIST_ENTRY *Node + ) +/*++ + +Routine Description: + + Determines whether the given node is null. Note that Node is null + when its value is equal to the value of List. It is an error for + Node to be the literal value NULL [(VOID*)0x0]. + +Arguments: + + List - The head of the list. MUST NOT be the literal value NULL. + Node - The node to test. MUST NOT be the literal value NULL. See + the description above. + +Returns: + + Returns true if the node is null. + +--*/ +{ + return (BOOLEAN)(Node == List); +} + + +BOOLEAN +IsNodeAtEnd ( + EFI_LIST_ENTRY *List, + EFI_LIST_ENTRY *Node + ) +/*++ + +Routine Description: + + Determines whether the given node is at the end of the list. Used + to walk the list. The list must have been initialized with + InitializeListHead () before using this function and must contain + data. + +Arguments: + + List - The head of the list. MUST NOT be the literal value NULL. + Node - The node to test. MUST NOT be the literal value NULL. + See the description of IsNull for more information. + +Returns: + + Returns true if the list is the tail. + +--*/ +{ + if (IsNull (List, Node)) { + return FALSE; + } + return (BOOLEAN)(List->BackLink == Node); +} + diff --git a/Library/LzmaDecode.c b/Library/LzmaDecode.c new file mode 100644 index 0000000..e48c135 --- /dev/null +++ b/Library/LzmaDecode.c @@ -0,0 +1,1592 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (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/LzmaDecode.c 1 8/25/10 6:10p Felixp $ +// +// $Revision: 1 $ +// +// $Date: 8/25/10 6:10p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/Library/LzmaDecode.c $ +// +// 1 8/25/10 6:10p Felixp +// +// 6 1/13/10 2:13p Felixp +// + + +//___________________________ + + +#ifndef __7Z_TYPES_H +#define __7Z_TYPES_H +/* +#ifdef EFIAPI + +#include "UefiLzma.h" + +#else + +#include + +#ifdef _WIN32 +#include +#endif + +#endif +*/ +#ifndef _PTRDIFF_T_DEFINED +typedef int ptrdiff_t; +#endif +#if defined(_WIN64) +typedef unsigned __int64 size_t; +#else +typedef unsigned int size_t; +typedef size_t _w_size_t; +#endif +#define SZ_OK 0 + +#define SZ_ERROR_DATA 1 +#define SZ_ERROR_MEM 2 +#define SZ_ERROR_CRC 3 +#define SZ_ERROR_UNSUPPORTED 4 +#define SZ_ERROR_PARAM 5 +#define SZ_ERROR_INPUT_EOF 6 +#define SZ_ERROR_OUTPUT_EOF 7 +#define SZ_ERROR_READ 8 +#define SZ_ERROR_WRITE 9 +#define SZ_ERROR_PROGRESS 10 +#define SZ_ERROR_FAIL 11 +#define SZ_ERROR_THREAD 12 + +#define SZ_ERROR_ARCHIVE 16 +#define SZ_ERROR_NO_ARCHIVE 17 + +typedef int SRes; + + +#ifndef RINOK +#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } +#endif + +typedef unsigned char Byte; +typedef short Int16; +typedef unsigned short UInt16; + +#ifdef _LZMA_UINT32_IS_ULONG +typedef long Int32; +typedef unsigned long UInt32; +#else +typedef int Int32; +typedef unsigned int UInt32; +#endif + +#ifdef _SZ_NO_INT_64 + +/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. + NOTES: Some code will work incorrectly in that case! */ + +typedef long Int64; +typedef unsigned long UInt64; + +#else + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#else +typedef long long int Int64; +typedef unsigned long long int UInt64; +#endif + +#endif + +#ifdef _LZMA_NO_SYSTEM_SIZE_T +#include +typedef UInt32 SizeT; +#else +typedef size_t SizeT; +#endif + +typedef int Bool; +#define True 1 +#define False 0 + + +#ifdef _MSC_VER + +#if _MSC_VER >= 1300 +#define MY_NO_INLINE __declspec(noinline) +#else +#define MY_NO_INLINE +#endif + +#define MY_CDECL __cdecl +#define MY_STD_CALL __stdcall +#define MY_FAST_CALL MY_NO_INLINE __fastcall + +#else + +#define MY_CDECL +#define MY_STD_CALL +#define MY_FAST_CALL + +#endif +#include +#define memcpy(a,b,c) MemCpy(a,(VOID*)(b),c) +#define memmove MemCpy +#define LShiftU64 Shl64 + +/* The following interfaces use first parameter as pointer to structure */ + +typedef struct +{ + SRes (*Read)(void *p, void *buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) < input(*size)) is allowed */ +} ISeqInStream; + +/* it can return SZ_ERROR_INPUT_EOF */ +SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); +SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); +SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); + +typedef struct +{ + size_t (*Write)(void *p, const void *buf, size_t size); + /* Returns: result - the number of actually written bytes. + (result < size) means error */ +} ISeqOutStream; + +typedef enum +{ + SZ_SEEK_SET = 0, + SZ_SEEK_CUR = 1, + SZ_SEEK_END = 2 +} ESzSeek; + +typedef struct +{ + SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ISeekInStream; + +typedef struct +{ + SRes (*Look)(void *p, void **buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) > input(*size)) is not allowed + (output(*size) < input(*size)) is allowed */ + SRes (*Skip)(void *p, size_t offset); + /* offset must be <= output(*size) of Look */ + + SRes (*Read)(void *p, void *buf, size_t *size); + /* reads directly (without buffer). It's same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ILookInStream; + +SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); +SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); + +/* reads via ILookInStream::Read */ +SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); +SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); + +#define LookToRead_BUF_SIZE (1 << 14) + +typedef struct +{ + ILookInStream s; + ISeekInStream *realStream; + size_t pos; + size_t size; + Byte buf[LookToRead_BUF_SIZE]; +} CLookToRead; + +void LookToRead_CreateVTable(CLookToRead *p, int lookahead); +void LookToRead_Init(CLookToRead *p); + +typedef struct +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToLook; + +void SecToLook_CreateVTable(CSecToLook *p); + +typedef struct +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToRead; + +void SecToRead_CreateVTable(CSecToRead *p); + +typedef struct +{ + SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); + /* Returns: result. (result != SZ_OK) means break. + Value (UInt64)(Int64)-1 for size means unknown value. */ +} ICompressProgress; + +typedef struct +{ + void *(*Alloc)(void *p, size_t size); + void (*Free)(void *p, void *address); /* address can be 0 */ +} ISzAlloc; + +#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) +#define IAlloc_Free(p, a) (p)->Free((p), a) + +#endif +//_________________________________________________________________ +/* #define _LZMA_PROB32 */ +/* _LZMA_PROB32 can increase the speed on some CPUs, + but memory usage for CLzmaDec::probs will be doubled in that case */ + +#ifdef _LZMA_PROB32 +#define CLzmaProb UInt32 +#else +#define CLzmaProb UInt16 +#endif + + +/* ---------- LZMA Properties ---------- */ + +#define LZMA_PROPS_SIZE 5 + +typedef struct _CLzmaProps +{ + unsigned lc, lp, pb; + UInt32 dicSize; +} CLzmaProps; + + + +/* ---------- LZMA Decoder state ---------- */ + +/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. + Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ + +#define LZMA_REQUIRED_INPUT_MAX 20 + +typedef struct +{ + CLzmaProps prop; + CLzmaProb *probs; + Byte *dic; + const Byte *buf; + UInt32 range, code; + SizeT dicPos; + SizeT dicBufSize; + UInt32 processedPos; + UInt32 checkDicSize; + unsigned state; + UInt32 reps[4]; + unsigned remainLen; + int needFlush; + int needInitState; + UInt32 numProbs; + unsigned tempBufSize; + Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; +} CLzmaDec; +/* There are two types of LZMA streams: + 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. + 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ + +typedef enum +{ + LZMA_FINISH_ANY, /* finish at any point */ + LZMA_FINISH_END /* block must be finished at the end */ +} ELzmaFinishMode; + +/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! + + You must use LZMA_FINISH_END, when you know that current output buffer + covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. + + If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, + and output value of destLen will be less than output buffer size limit. + You can check status result also. + + You can use multiple checks to test data integrity after full decompression: + 1) Check Result and "status" variable. + 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. + 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. + You must use correct finish mode in that case. */ + +typedef enum +{ + LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ + LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ + LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ + LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ +} ELzmaStatus; + +#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } +#define SIZE_64KB 0x10000 +#define SCRATCH_BUFFER_REQUEST_SIZE SIZE_64KB + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_INIT_SIZE 5 + +#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); +#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); +#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ + { UPDATE_0(p); i = (i + i); A0; } else \ + { UPDATE_1(p); i = (i + i) + 1; A1; } +#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) + +#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } +#define TREE_DECODE(probs, limit, i) \ + { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } + +/* #define _LZMA_SIZE_OPT */ + +#ifdef _LZMA_SIZE_OPT +#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) +#else +#define TREE_6_DECODE(probs, i) \ + { i = 1; \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + i -= 0x40; } +#endif + +#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0_CHECK range = bound; +#define UPDATE_1_CHECK range -= bound; code -= bound; +#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ + { UPDATE_0_CHECK; i = (i + i); A0; } else \ + { UPDATE_1_CHECK; i = (i + i) + 1; A1; } +#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) +#define TREE_DECODE_CHECK(probs, limit, i) \ + { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + + +#define kNumStates 12 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 +#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +static const Byte kLiteralNextStates[kNumStates * 2] = +{ + 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5, + 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 +}; + +#define LZMA_DIC_MIN (1 << 12) + +/* First LZMA-symbol is always decoded. +And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization +Out: + Result: + SZ_OK - OK + SZ_ERROR_DATA - Error + p->remainLen: + < kMatchSpecLenStart : normal remain + = kMatchSpecLenStart : finished + = kMatchSpecLenStart + 1 : Flush marker + = kMatchSpecLenStart + 2 : State Init Marker +*/ + +static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + CLzmaProb *probs = p->probs; + + unsigned state = p->state; + UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; + unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; + unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; + unsigned lc = p->prop.lc; + + Byte *dic = p->dic; + SizeT dicBufSize = p->dicBufSize; + SizeT dicPos = p->dicPos; + + UInt32 processedPos = p->processedPos; + UInt32 checkDicSize = p->checkDicSize; + unsigned len = 0; + + const Byte *buf = p->buf; + UInt32 range = p->range; + UInt32 code = p->code; + + do + { + CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = processedPos & pbMask; + + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + IF_BIT_0(prob) + { + unsigned symbol; + UPDATE_0(prob); + prob = probs + Literal; + if (checkDicSize != 0 || processedPos != 0) + prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + + (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); + + if (state < kNumLitStates) + { + symbol = 1; + do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); + } + else + { + unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + unsigned offs = 0x100; + symbol = 1; + do + { + unsigned bit; + CLzmaProb *probLit; + matchByte <<= 1; + bit = (matchByte & offs); + probLit = prob + offs + bit + symbol; + GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) + } + while (symbol < 0x100); + } + dic[dicPos++] = (Byte)symbol; + processedPos++; + + state = kLiteralNextStates[state]; + /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */ + continue; + } + else + { + UPDATE_1(prob); + prob = probs + IsRep + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + state += kNumStates; + prob = probs + LenCoder; + } + else + { + UPDATE_1(prob); + if (checkDicSize == 0 && processedPos == 0) + return SZ_ERROR_DATA; + prob = probs + IsRepG0 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; + IF_BIT_0(prob) + { + UPDATE_0(prob); + dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + dicPos++; + processedPos++; + state = state < kNumLitStates ? 9 : 11; + continue; + } + UPDATE_1(prob); + } + else + { + UInt32 distance; + UPDATE_1(prob); + prob = probs + IsRepG1 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep1; + } + else + { + UPDATE_1(prob); + prob = probs + IsRepG2 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep2; + } + else + { + UPDATE_1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = probs + RepLenCoder; + } + { + unsigned limit2, offset; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + limit2 = (1 << kLenNumLowBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenChoice2; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + limit2 = (1 << kLenNumMidBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + limit2 = (1 << kLenNumHighBits); + } + } + TREE_DECODE(probLen, limit2, len); + len += offset; + } + + if (state >= kNumStates) + { + UInt32 distance; + prob = probs + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); + TREE_6_DECODE(prob, distance); + if (distance >= kStartPosModelIndex) + { + unsigned posSlot = (unsigned)distance; + int numDirectBits = (int)(((distance >> 1) - 1)); + distance = (2 | (distance & 1)); + if (posSlot < kEndPosModelIndex) + { + distance <<= numDirectBits; + prob = probs + SpecPos + distance - posSlot - 1; + { + UInt32 mask = 1; + unsigned i = 1; + do + { + GET_BIT2(prob + i, i, ; , distance |= mask); + mask <<= 1; + } + while (--numDirectBits != 0); + } + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE + range >>= 1; + + { + UInt32 t; + code -= range; + t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ + distance = (distance << 1) + (t + 1); + code += range & t; + } + /* + distance <<= 1; + if (code >= range) + { + code -= range; + distance |= 1; + } + */ + } + while (--numDirectBits != 0); + prob = probs + Align; + distance <<= kNumAlignBits; + { + unsigned i = 1; + GET_BIT2(prob + i, i, ; , distance |= 1); + GET_BIT2(prob + i, i, ; , distance |= 2); + GET_BIT2(prob + i, i, ; , distance |= 4); + GET_BIT2(prob + i, i, ; , distance |= 8); + } + if (distance == (UInt32)0xFFFFFFFF) + { + len += kMatchSpecLenStart; + state -= kNumStates; + break; + } + } + } + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = distance + 1; + if (checkDicSize == 0) + { + if (distance >= processedPos) + return SZ_ERROR_DATA; + } + else if (distance >= checkDicSize) + return SZ_ERROR_DATA; + state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; + /* state = kLiteralNextStates[state]; */ + } + + len += kMatchMinLen; + + if (limit == dicPos) + return SZ_ERROR_DATA; + { + SizeT rem = limit - dicPos; + unsigned curLen = ((rem < len) ? (unsigned)rem : len); + SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); + + processedPos += curLen; + + len -= curLen; + if (pos + curLen <= dicBufSize) + { + Byte *dest = dic + dicPos; + ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; + const Byte *lim = dest + curLen; + dicPos += curLen; + do + *(dest) = (Byte)*(dest + src); + while (++dest != lim); + } + else + { + do + { + dic[dicPos++] = dic[pos]; + if (++pos == dicBufSize) + pos = 0; + } + while (--curLen != 0); + } + } + } + } + while (dicPos < limit && buf < bufLimit); + NORMALIZE; + p->buf = buf; + p->range = range; + p->code = code; + p->remainLen = len; + p->dicPos = dicPos; + p->processedPos = processedPos; + p->reps[0] = rep0; + p->reps[1] = rep1; + p->reps[2] = rep2; + p->reps[3] = rep3; + p->state = state; + + return SZ_OK; +} + +static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) +{ + if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) + { + Byte *dic = p->dic; + SizeT dicPos = p->dicPos; + SizeT dicBufSize = p->dicBufSize; + unsigned len = p->remainLen; + UInt32 rep0 = p->reps[0]; + if (limit - dicPos < len) + len = (unsigned)(limit - dicPos); + + if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) + p->checkDicSize = p->prop.dicSize; + + p->processedPos += len; + p->remainLen -= len; + while (len-- != 0) + { + dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + dicPos++; + } + p->dicPos = dicPos; + } +} + +static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + do + { + SizeT limit2 = limit; + if (p->checkDicSize == 0) + { + UInt32 rem = p->prop.dicSize - p->processedPos; + if (limit - p->dicPos > rem) + limit2 = p->dicPos + rem; + } + RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); + if (p->processedPos >= p->prop.dicSize) + p->checkDicSize = p->prop.dicSize; + LzmaDec_WriteRem(p, limit); + } + while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); + + if (p->remainLen > kMatchSpecLenStart) + { + p->remainLen = kMatchSpecLenStart; + } + return 0; +} + +typedef enum +{ + DUMMY_ERROR, /* unexpected end of input stream */ + DUMMY_LIT, + DUMMY_MATCH, + DUMMY_REP +} ELzmaDummy; + +static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) +{ + UInt32 range = p->range; + UInt32 code = p->code; + const Byte *bufLimit = buf + inSize; + CLzmaProb *probs = p->probs; + unsigned state = p->state; + ELzmaDummy res; + + { + CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); + + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK + + /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ + + prob = probs + Literal; + if (p->checkDicSize != 0 || p->processedPos != 0) + prob += (LZMA_LIT_SIZE * + ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + + (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); + + if (state < kNumLitStates) + { + unsigned symbol = 1; + do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); + } + else + { + unsigned matchByte = p->dic[p->dicPos - p->reps[0] + + ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; + unsigned offs = 0x100; + unsigned symbol = 1; + do + { + unsigned bit; + CLzmaProb *probLit; + matchByte <<= 1; + bit = (matchByte & offs); + probLit = prob + offs + bit + symbol; + GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) + } + while (symbol < 0x100); + } + res = DUMMY_LIT; + } + else + { + unsigned len; + UPDATE_1_CHECK; + + prob = probs + IsRep + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + state = 0; + prob = probs + LenCoder; + res = DUMMY_MATCH; + } + else + { + UPDATE_1_CHECK; + res = DUMMY_REP; + prob = probs + IsRepG0 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + NORMALIZE_CHECK; + return DUMMY_REP; + } + else + { + UPDATE_1_CHECK; + } + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG1 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG2 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + } + } + } + state = kNumStates; + prob = probs + RepLenCoder; + } + { + unsigned limit, offset; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + limit = 1 << kLenNumLowBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenChoice2; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + limit = 1 << kLenNumMidBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + limit = 1 << kLenNumHighBits; + } + } + TREE_DECODE_CHECK(probLen, limit, len); + len += offset; + } + + if (state < 4) + { + unsigned posSlot; + prob = probs + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + + /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ + + if (posSlot < kEndPosModelIndex) + { + prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE_CHECK + range >>= 1; + code -= range & (((code - range) >> 31) - 1); + /* if (code >= range) code -= range; */ + } + while (--numDirectBits != 0); + prob = probs + Align; + numDirectBits = kNumAlignBits; + } + { + unsigned i = 1; + do + { + GET_BIT_CHECK(prob + i, i); + } + while (--numDirectBits != 0); + } + } + } + } + } + NORMALIZE_CHECK; + return res; +} + +static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) +{ + p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); + p->range = 0xFFFFFFFF; + p->needFlush = 0; +} + +void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) +{ + p->needFlush = 1; + p->remainLen = 0; + p->tempBufSize = 0; + + if (initDic) + { + p->processedPos = 0; + p->checkDicSize = 0; + p->needInitState = 1; + } + if (initState) + p->needInitState = 1; +} + +void LzmaDec_Init(CLzmaDec *p) +{ + p->dicPos = 0; + LzmaDec_InitDicAndState(p, True, True); +} + +static void LzmaDec_InitStateReal(CLzmaDec *p) +{ + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); + UInt32 i; + CLzmaProb *probs = p->probs; + for (i = 0; i < numProbs; i++) + probs[i] = kBitModelTotal >> 1; + p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; + p->state = 0; + p->needInitState = 0; +} +/* LzmaDec_DecodeToDic + + The decoding to internal dictionary buffer (CLzmaDec::dic). + You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! + +finishMode: + It has meaning only if the decoding reaches output limit (dicLimit). + LZMA_FINISH_ANY - Decode just dicLimit bytes. + LZMA_FINISH_END - Stream must be finished after dicLimit. + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_NEEDS_MORE_INPUT + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error +*/ +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, + ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT inSize = *srcLen; + (*srcLen) = 0; + LzmaDec_WriteRem(p, dicLimit); + + *status = LZMA_STATUS_NOT_SPECIFIED; + + while (p->remainLen != kMatchSpecLenStart) + { + int checkEndMarkNow; + + if (p->needFlush != 0) + { + for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) + p->tempBuf[p->tempBufSize++] = *src++; + if (p->tempBufSize < RC_INIT_SIZE) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (p->tempBuf[0] != 0) + return SZ_ERROR_DATA; + + LzmaDec_InitRc(p, p->tempBuf); + p->tempBufSize = 0; + } + + checkEndMarkNow = 0; + if (p->dicPos >= dicLimit) + { + if (p->remainLen == 0 && p->code == 0) + { + *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; + return SZ_OK; + } + if (finishMode == LZMA_FINISH_ANY) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_OK; + } + if (p->remainLen != 0) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + checkEndMarkNow = 1; + } + + if (p->needInitState) + LzmaDec_InitStateReal(p); + + if (p->tempBufSize == 0) + { + SizeT processed; + const Byte *bufLimit; + if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + int dummyRes = LzmaDec_TryDummy(p, src, inSize); + if (dummyRes == DUMMY_ERROR) + { + memcpy(p->tempBuf, src, inSize); + p->tempBufSize = (unsigned)inSize; + (*srcLen) += inSize; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + bufLimit = src; + } + else + bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; + p->buf = src; + if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) + return SZ_ERROR_DATA; + processed = (SizeT)(p->buf - src); + (*srcLen) += processed; + src += processed; + inSize -= processed; + } + else + { + unsigned rem = p->tempBufSize, lookAhead = 0; + while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) + p->tempBuf[rem++] = src[lookAhead++]; + p->tempBufSize = rem; + if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); + if (dummyRes == DUMMY_ERROR) + { + (*srcLen) += lookAhead; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + } + p->buf = p->tempBuf; + if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) + return SZ_ERROR_DATA; + lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); + (*srcLen) += lookAhead; + src += lookAhead; + inSize -= lookAhead; + p->tempBufSize = 0; + } + } + if (p->code == 0) + *status = LZMA_STATUS_FINISHED_WITH_MARK; + return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; +} +/* It's zlib-like interface. + See LzmaDec_DecodeToDic description for information about STEPS and return results, + but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need + to work with CLzmaDec variables manually. + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). +*/ +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT outSize = *destLen; + SizeT inSize = *srcLen; + *srcLen = *destLen = 0; + for (;;) + { + SizeT inSizeCur = inSize, outSizeCur, dicPos; + ELzmaFinishMode curFinishMode; + SRes res; + if (p->dicPos == p->dicBufSize) + p->dicPos = 0; + dicPos = p->dicPos; + if (outSize > p->dicBufSize - dicPos) + { + outSizeCur = p->dicBufSize; + curFinishMode = LZMA_FINISH_ANY; + } + else + { + outSizeCur = dicPos + outSize; + curFinishMode = finishMode; + } + + res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); + src += inSizeCur; + inSize -= inSizeCur; + *srcLen += inSizeCur; + outSizeCur = p->dicPos - dicPos; + memcpy(dest, p->dic + dicPos, outSizeCur); + dest += outSizeCur; + outSize -= outSizeCur; + *destLen += outSizeCur; + if (res != 0) + return res; + if (outSizeCur == 0 || outSize == 0) + return SZ_OK; + } +} + +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->probs); + p->probs = 0; +} + +static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->dic); + p->dic = 0; +} + +void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) +{ + LzmaDec_FreeProbs(p, alloc); + LzmaDec_FreeDict(p, alloc); +} + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) +{ + UInt32 dicSize; + Byte d; + + if (size < LZMA_PROPS_SIZE) + return SZ_ERROR_UNSUPPORTED; + else + dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); + + if (dicSize < LZMA_DIC_MIN) + dicSize = LZMA_DIC_MIN; + p->dicSize = dicSize; + + d = data[0]; + if (d >= (9 * 5 * 5)) + return SZ_ERROR_UNSUPPORTED; + + p->lc = d % 9; + d /= 9; + p->pb = d / 5; + p->lp = d % 5; + + return SZ_OK; +} + +static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) +{ + UInt32 numProbs = LzmaProps_GetNumProbs(propNew); + if (p->probs == 0 || numProbs != p->numProbs) + { + LzmaDec_FreeProbs(p, alloc); + p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); + p->numProbs = numProbs; + if (p->probs == 0) + return SZ_ERROR_MEM; + } + return SZ_OK; +} + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +{ + CLzmaProps propNew; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +{ + CLzmaProps propNew; + SizeT dicBufSize; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + dicBufSize = propNew.dicSize; + if (p->dic == 0 || dicBufSize != p->dicBufSize) + { + LzmaDec_FreeDict(p, alloc); + p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); + if (p->dic == 0) + { + LzmaDec_FreeProbs(p, alloc); + return SZ_ERROR_MEM; + } + } + p->dicBufSize = dicBufSize; + p->prop = propNew; + return SZ_OK; +} +/* LzmaDecode + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). +*/ +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAlloc *alloc) +{ + CLzmaDec p; + SRes res; + SizeT inSize = *srcLen; + SizeT outSize = *destLen; + *srcLen = *destLen = 0; + if (inSize < RC_INIT_SIZE) + return SZ_ERROR_INPUT_EOF; + + LzmaDec_Construct(&p); + res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); + if (res != 0) + return res; + p.dic = dest; + p.dicBufSize = outSize; + + LzmaDec_Init(&p); + + *srcLen = inSize; + res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); + + if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) + res = SZ_ERROR_INPUT_EOF; + + (*destLen) = p.dicPos; + LzmaDec_FreeProbs(&p, alloc); + return res; +} + + +typedef struct +{ + ISzAlloc Functions; + VOID *Buffer; + UINTN BufferSize; +} ISzAllocWithData; + +/** + Allocation routine used by LZMA decompression. + + @param P Pointer to the ISzAlloc instance + @param Size The size in bytes to be allocated + + @return The allocated pointer address, or NULL on failure +**/ +VOID * +SzAlloc ( + VOID *P, + size_t Size + ) +{ + VOID *Addr; + ISzAllocWithData *Private; + + Private = (ISzAllocWithData*) P; + + if (Private->BufferSize >= Size) { + Addr = Private->Buffer; + Private->Buffer = (VOID*) ((UINT8*)Addr + Size); + Private->BufferSize -= Size; + return Addr; + } else { +// ASSERT (FALSE); + return NULL; + } +} + +/** + Free routine used by LZMA decompression. + + @param P Pointer to the ISzAlloc instance + @param Address The address to be freed +**/ +VOID +SzFree ( + VOID *P, + VOID *Address + ) +{ + // + // We use the 'scratch buffer' for allocations, so there is no free + // operation required. The scratch buffer will be freed by the caller + // of the decompression code. + // +} + +#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8) + +/** + Get the size of the uncompressed buffer by parsing EncodeData header. + + @param EncodedData Pointer to the compressed data. + + @return The size of the uncompressed buffer. +**/ +UINT64 +GetDecodedSizeOfBuf( + UINT8 *EncodedData + ) +{ + UINT64 DecodedSize; + INTN Index; + + /* Parse header */ + DecodedSize = 0; + for (Index = LZMA_PROPS_SIZE + 7; Index >= LZMA_PROPS_SIZE; Index--) + DecodedSize = LShiftU64(DecodedSize, 8) + EncodedData[Index]; + + return DecodedSize; +} + +// +//-------------------------------------------------------------------------- +// Procedure: LzmaGetInfo +// +// Description: LZMA implementation of GetInfo() routine of the decompress protocol +// +// Input: +// Source - The source buffer containing the compressed data. +// SourceSize - The size of source buffer +// +// Output: +// DestinationSize - The size of destination buffer. +// ScratchSize - The size of scratch buffer. +// +// Return: +// EFI_SUCCESS - The size of destination buffer and the size of scratch buffer +// are successull retrieved. +// EFI_INVALID_PARAMETER - The source data is corrupted +// +//-------------------------------------------------------------------------- +// +EFI_STATUS LzmaGetInfo ( + IN CONST VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ) +{ + UInt64 DecodedSize; + + if (SourceSize <= LZMA_HEADER_SIZE) return EFI_INVALID_PARAMETER; + + DecodedSize = GetDecodedSizeOfBuf((UINT8*)Source); + + *DestinationSize = (UINT32)DecodedSize; + *ScratchSize = SCRATCH_BUFFER_REQUEST_SIZE; + return EFI_SUCCESS; +} + +// +//-------------------------------------------------------------------------- +// Procedure: LzmaDecompress +// +// Description: LZMA implementation of Decompress() routine of the decompress protocol +// +// Input: +// Source - The source buffer containing the compressed data. +// SrcSize - The size of source buffer +// Destination - The destination buffer to store the decompressed data +// DstSize - The size of destination buffer. +// Scratch - The buffer used internally by the decompress routine. +// This buffer is provided to store intermediate data. +// ScratchSize - The size of scratch buffer. +// +// Output: +// Destination - The destination buffer to store the decompressed data +// +// Return: +// EFI_SUCCESS - Decompression is successfull +// EFI_INVALID_PARAMETER - The source data is corrupted +// +//-------------------------------------------------------------------------- +// +EFI_STATUS LzmaDecompress ( + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize +) +{ + SRes LzmaResult; + ELzmaStatus Status; + SizeT DecodedBufSize; + SizeT EncodedDataSize; + ISzAllocWithData AllocFuncs; + + AllocFuncs.Functions.Alloc = SzAlloc; + AllocFuncs.Functions.Free = SzFree; + AllocFuncs.Buffer = Scratch; + AllocFuncs.BufferSize = SCRATCH_BUFFER_REQUEST_SIZE; + + DecodedBufSize = (SizeT)GetDecodedSizeOfBuf((UINT8*)Source); + if ((DecodedBufSize > DstSize) || (ScratchSize < SCRATCH_BUFFER_REQUEST_SIZE)) + return EFI_INVALID_PARAMETER; + else DecodedBufSize = DstSize; + EncodedDataSize = (SizeT) (SrcSize - LZMA_HEADER_SIZE); + + LzmaResult = LzmaDecode( + Destination, + &DecodedBufSize, + (Byte*)((UINT8*)Source + LZMA_HEADER_SIZE), + &EncodedDataSize, + Source, + LZMA_PROPS_SIZE, + LZMA_FINISH_END, + &Status, + &(AllocFuncs.Functions) + ); + + if (LzmaResult == SZ_OK) { + return EFI_SUCCESS; + } else { + return EFI_INVALID_PARAMETER; + } +} + + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** \ No newline at end of file diff --git a/Library/Memory.c b/Library/Memory.c new file mode 100644 index 0000000..387474f --- /dev/null +++ b/Library/Memory.c @@ -0,0 +1,340 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//************************************************************************* +// $Header: /Alaska/SOURCE/Core/Library/Memory.c 10 1/19/12 5:00p Markw $ +// +// $Revision: 10 $ +// +// $Date: 1/19/12 5:00p $ +//************************************************************************* +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/Library/Memory.c $ +// +// 10 1/19/12 5:00p Markw +// [TAG] EIP81447 +// [Category] Improvement +// [Description] Update page tables to use only 2 MB page tables below 4 +// GB. +// Vista/Win7/Win2008 server doesn't parse 1 GB page tables correctly. +// [Files] memory.c +// +// 9 4/26/11 10:45p Markw +// [TAG] EIP58991 +// [Category] Improvement +// [Description] Support 1 GB page table size in 64-bit mode in DXE. +// [Files] memory.c +// +// 8 7/10/09 3:49p Felixp +// Function headers added +// +// 7 5/02/08 9:57a Felixp +// Bug fix in FillPageTable (Systems with x64 firmware and more than 4GB +// of memory were resetting during transition to DXE) +// +// 6 4/17/08 3:27p Markw +// Add paging functions. +// +// 5 8/24/06 9:26a Felixp +// Preliminary x64 support (work in progress): +// 1. Processor architecture specific functions moved to a processor +// library +// 2. Makefile removed (AmiLib files are build by the AmiPeiLib and +// AmeDxeLib makefile) +// 3. Tokens.c added +// +// 4 6/22/05 12:52p Felixp +// MemSet changes: bug fix (problem with Counter<4); comments added +// +// 3 3/04/05 10:50a Mandal +// +//************************************************************************* +// +// +// Name: Memory.c +// +// Description: +// Contains memory related library functions. +// +// +//************************************************************************* +#include +#include + +//************************************************************************* +// +// +// Name: Memory_Functions +// +// Description: +// Memory functions defined in the AMI library. Note some may only be +// available in DXE. +// +// Fields: Header Function Description +// ------------------------------------------------------------------ +// AmiLib MemSet Fills a buffer with a user provided value. +// AmiLib MemCmp Compare two buffers for equality. +// AmiLIb MemCpy Copy a buffer into another buffer. +// AmiDxeLib Malloc Allocate memory from EfiBootServicesData. +// AmiDxeLib MallocZ Allocate memory from EfiBootServicesData that has been cleared with zeros. +// +// Notes: +// Header details which header file contains the function prototype for +// the above functions. Append .h to the given name. +// +// +//************************************************************************* + +VOID CPULib_CpuID(IN UINT32 CpuIDIndex, OUT UINT32 *RegEAX, OUT UINT32 *RegEBX, + IN OUT UINT32 *RegECX, OUT UINT32 *RegEDX); + +//************************************************************************* +// +// +// Name: MemCmp +// +// Description: +// INTN MemCmp(IN VOID* pDestination, IN VOID* pSource, IN UINTN Count) +// compares Length bytes of pDestination to Length bytes of pSource. If all +// Length bytes of the two buffers are identical, then 0 is returned. +// Otherwise, the value returned is the first mismatched byte in pSource +// subtracted from the first mismatched byte in pDestination. +// +// Input: +// IN VOID* pDestination +// Pointer to the first buffer to compare. +// +// IN VOID* pSource +// Pointer to the second buffer to compare. +// +// IN UINTN Count +// Number of bytes to compare. +// +// Output: +// INTN value of first mismatched byte in pSource subtracted from the first +// mismatched byte in pDestination (pDestination - pSource). Returns 0 if +// both buffers are the same. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +INTN MemCmp(VOID* pDestination, VOID* pSource, UINTN Count){ + INT8 *d = (UINT8*)pDestination, *s = (UINT8*)pSource; + INT8 *end=d+Count; + UINTN r; +//////////////////////////////////////////////////////////// +// NOTE: in order to increase the comparison speed we will +// compare sizeof(UINTN) bytes at a time if possible. +// Once inequality is found, we will go to the last while loop +// to do a byte by byte comparison to get proper results. +// We have to do it because of the following: +// Let's say we are trying to compare values: 0x1234 and 0x4321: +// If we compare them as double words the second value will be greater. +// If we compare them byte by byte the first value wiill be greater +// (because of little endian architecture of x86) +//////////////////////////////////////////////////////////// + if (Count >= sizeof(UINTN)){ + r = (UINTN)d & (sizeof(UINTN)-1); + if (r && r== ((UINTN)s & (sizeof(UINTN)-1))){ + r = sizeof(UINTN)-r; + Count-=r; + for(;r;r--) + if (*d==*s){d++;s++;} + //the values are not equal + //let's break to do a byte by byte comparison + //to figure out which one is greater + else break; + } + while(d<=end-sizeof(UINTN)) + if (*(UINTN*)d==*(UINTN*)s){ + d+=sizeof(UINTN);s+=sizeof(UINTN); + } + //the values are not equal + //let's break to do a byte by byte comparison + //to figure out which one is greater + else break; + } + while(d +// +// Name: GetPageTableNumPages +// +// Description: +// UINT32 GetPageTableNumPages(IN UINT8 NumberMemoryBits) gets the number +// of pages to allocate for paging. +// Unlimited if 1 GB page tables is supported. Otherwise, limit 512 MB address space. +// +// Input: +// IN UINT8 NumberMemoryBits +// Number of memory bits to map. +// +// Output: +// UINT32 number of pages. +// +// Modified: +// +// Referrals: +// Shl64 +// CPULib_CpuID +// +// Notes: +// +// +//************************************************************************* +UINT32 GetPageTableNumPages( + IN UINT8 NumberMemoryBits +) +{ + BOOLEAN GigPageSupport; + UINT32 RegEax, RegEbx, RegEcx, RegEdx; + UINT32 NumPages; + + CPULib_CpuID(0x80000001, &RegEax, &RegEbx, &RegEcx, &RegEdx); + GigPageSupport = !!(RegEdx & BIT26); + + //Limit number of memory bits to 39 (512 GB) if no support for GB page-tables. + if (!GigPageSupport && NumberMemoryBits > 39) NumberMemoryBits = 39; + + if (GigPageSupport) { + //1 page for PML4E Table. + //4 page for for Directory. First 4GB of 2MB pages. + //1 Page for Page-Table Entries for 1st 2MB of 4k pages. + NumPages = 6; + + //Allocate pages for directory pointers. + NumPages += 1 << (NumberMemoryBits > 39 ? NumberMemoryBits - 39 : 0); + } else { + //Allocate at least 7 pages to cover Identity Mapping for 32 bits. + //1 page for PML4E Table + //1 page for Page-Directory Pointer + //Pages for Directory allocated later--one for each directory. + //1 page for Page-Table Entries for 1st 2MB. This must be 4k blocks. + NumPages = 3; + + //Allocate pages for page directories. + NumPages += 1 << (NumberMemoryBits - 30); + } + return NumPages; +} + +//************************************************************************* +// +// +// Name: FillPageTable +// +// Description: +// VOID FillPageTable(IN UINT8 NumberMemoryBits, IN VOID *PageTable) fills a +// provided page table with an identity map. +// +// Input: +// IN UINT8 NumberMemoryBits +// Number of memory bits to map. +// +// IN VOID *PageTable +// Page table to fill. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// Shl64 +// MemSet +// CPULib_CpuID +// +// Notes: +// +// +//************************************************************************* +VOID FillPageTable( + IN UINT8 NumberMemoryBits, + IN VOID *PageTable +) +{ + BOOLEAN GigPageSupport; + UINT32 RegEax, RegEbx, RegEcx, RegEdx; + UINT64 *Pml4eTable = (UINT64*)PageTable; + UINT64 *PdpTable = (UINT64*)((UINT8*)PageTable + 0x1000); + UINT64 *PDir; + UINT64 *PTableEntry; + UINT32 NumPml4Entries; + UINT32 NumPgDirPtrEntries; + UINT32 NumPgDirEntries; + UINT32 i; + + CPULib_CpuID(0x80000001, &RegEax, &RegEbx, &RegEcx, &RegEdx); + GigPageSupport = !!(RegEdx & BIT26); + + //Limit number of memory bits to 39 (512 GB) if no support for GB page-tables. + if (!GigPageSupport && NumberMemoryBits > 39) NumberMemoryBits = 39; + + // Update Page-Map Level-4 tables. + NumPml4Entries = 1 << (NumberMemoryBits > 39 ? NumberMemoryBits - 39 : 0); + for (i = 0; i < NumPml4Entries; ++i) Pml4eTable[i] = BIT0 + BIT1 + (i << 12) + (UINT64)(UINTN)PdpTable; + MemSet(Pml4eTable + i, 4096 - 8 * i, 0); //Clear unused entries. + + //Update Page Pointer Directories. + NumPgDirPtrEntries = 1 << (NumberMemoryBits - 30); + PDir = PdpTable + (NumPgDirPtrEntries <= 512 ? 512 : NumPgDirPtrEntries); + if (GigPageSupport) { + //1st 4 pages must point to a Page directory + PdpTable[0] = BIT0 + BIT1 + (0 << 12) + (UINT64)(UINTN)PDir; + PdpTable[1] = BIT0 + BIT1 + (1 << 12) + (UINT64)(UINTN)PDir; + PdpTable[2] = BIT0 + BIT1 + (2 << 12) + (UINT64)(UINTN)PDir; + PdpTable[3] = BIT0 + BIT1 + (3 << 12) + (UINT64)(UINTN)PDir; + for (i = 4; i < NumPgDirPtrEntries; ++i) + PdpTable[i] = BIT0 + BIT1 + BIT7 + Shl64(i, 30); + } else { + for (i = 0; i < NumPgDirPtrEntries; ++i) + PdpTable[i] = BIT0 + BIT1 + (i << 12) + (UINT64)(UINTN)PDir; + } + if (i < 512) MemSet(PdpTable + i, 4096 - 8 * i, 0); //Clear unused entries. + + //Initialize Page Directores. + if (GigPageSupport) NumPgDirEntries = 2048; //First 4 GB + else NumPgDirEntries = 1 << (NumberMemoryBits - 21); //Number of 2MB pages. + PTableEntry = PDir + NumPgDirEntries; + PDir[0] = BIT0 + BIT1 + (UINT64)(UINTN)PTableEntry; //4K Page Table for first 2MB. + for(i = 1; i < NumPgDirEntries; ++i) PDir[i] = 0x83 + Shl64(i, 21); + + //Initialize 4k page entries for first 2MB. + for(i = 0; i < 512; ++i) PTableEntry[i] = BIT0 + BIT1 + (i << 12); +} + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Library/Misc.c b/Library/Misc.c new file mode 100644 index 0000000..a7bd330 --- /dev/null +++ b/Library/Misc.c @@ -0,0 +1,220 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//************************************************************************* +// $Header: /Alaska/SOURCE/Core/Library/Misc.c 8 5/22/12 4:14p Oleksiyy $ +// +// $Revision: 8 $ +// +// $Date: 5/22/12 4:14p $ +//************************************************************************* +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/Library/Misc.c $ +// +// 8 5/22/12 4:14p Oleksiyy +// [TAG] EIP90322 +// [Category] Improvement +// [Description] Declaration of AMI Global Variable Guid is added. +// [Files] Misc.c and AmiLib.h +// +// 7 7/10/09 3:49p Felixp +// Function headers added +// +// 6 4/03/06 5:07p Felixp +// ExecScript function added +// +// 5 3/04/05 10:50a Mandal +// +// 4 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 3 1/14/05 1:17p Felixp +// +// 2 1/14/05 1:14p Felixp +// FindNextHobByGuid added +// +// 1 12/23/04 9:41a Felixp +// +// 2 11/18/04 6:09p Felixp +// +// 1 11/18/04 10:52a Felixp +// +//************************************************************************* +// +// +// Name: Misc.c +// +// Description: +// Miscellaneous generic library functions. +// +// +//************************************************************************* +#include +#include + +EFI_GUID gAmiGlobalVariableGuid = AMI_GLOBAL_VARIABLE_GUID; + +//************************************************************************* +// +// +// Name: FindNextHobByType +// +// Description: +// EFI_STATUS FindNextHobByType(IN UINT16 Type, IN OUT VOID **Hob) finds a +// HOB with a specified Type starting from the HOB that comes after the HOB +// pointed by *Hob. *Hob pointer is updated with the address of the found +// HOB. +// +// Input: +// IN UINT16 Type +// Type of HOB to return. +// +// IN OUT VOID **Hob +// Address of the HOB if found. Otherwise unchanged. +// +// Output: +// EFI_INVALID_PARAMETER, if Hob = NULL. +// EFI_NOT_FOUND, if HOB of specified type not found. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// NextHob +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS FindNextHobByType(IN UINT16 Type, IN OUT VOID **Hob) +{ + EFI_HOB_GENERIC_HEADER *ThisHob; + if (Hob == NULL) return EFI_INVALID_PARAMETER; + ThisHob = *Hob; + while(ThisHob->HobType != EFI_HOB_TYPE_END_OF_HOB_LIST) { + ThisHob=NextHob(ThisHob,EFI_HOB_GENERIC_HEADER); + if (ThisHob->HobType==Type) { + *Hob=ThisHob; + return EFI_SUCCESS; + } + } + return EFI_NOT_FOUND; +} + +//************************************************************************* +// +// +// Name: FindNextHobByGuid +// +// Description: +// EFI_STATUS FindNextHobByGuid(IN EFI_GUID *Guid, IN OUT VOID **Hob) finds +// HOB of type Guid Extention with a specified GUID starting from the HOB +// that comes after the HOB pointed by *Hob. *Hob pointer is updated with +// the address of the found HOB. +// +// Input: +// IN EFI_GUID *Guid +// GUID for specific Guid Extention HOB. +// +// IN OUT VOID **Hob +// Address of the HOB if found. Otherwise unchanged. +// +// Output: +// EFI_INVALID_PARAMETER, if Hob = NULL. +// EFI_NOT_FOUND, if HOB of specified type not found. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// FindNextHobByType +// guidcmp +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS FindNextHobByGuid(IN EFI_GUID *Guid, IN OUT VOID **Hob) +{ + EFI_HOB_GUID_TYPE *ThisHob; + EFI_STATUS Status; + + if (!Guid||!Hob) return EFI_INVALID_PARAMETER; + + ThisHob=*Hob; + + for(;;){ + Status = FindNextHobByType(EFI_HOB_TYPE_GUID_EXTENSION,&ThisHob); + if (EFI_ERROR(Status)) return Status; + if (!guidcmp(&ThisHob->Name,Guid)) { + *Hob = ThisHob; + return EFI_SUCCESS; + } + } +} + +//************************************************************************* +// +// +// Name: ExecScript +// +// Description: +// EFI_STATUS ExecScript(IN IO_DATA *ScriptData, IN UINTN EntryCount) +// executes a sequence of CPU I/O operations. +// +// Input: +// IN IO_DATA *ScriptData +// Pointer to the first element of an IO_DATA table. +// +// IN UINTN EntryCount +// Number of entries in the IO_DATA table. +// +// Output: +// EFI_INVALID_PARAMETER, if a width or address within the table is invalid. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// IoWrite +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS ExecScript(IO_DATA *ScriptData, UINTN EntryCount){ + UINTN i; + EFI_STATUS Status; +//---------------------- + for(i=0; i +// +// Name: PELoader.c +// +// Description: +// Loader functions for PE32/PE32+ files. +// The functions are used by Core to implement standard image loading API. +// Consumers outside Core should not use functions from this file. +// The public API should be used instead. +// +// +//************************************************************************* +#include +/************************************************************************/ +/* PE Loader */ +/************************************************************************/ +#define PE32_SUPPORT (PE_LOADER_SUPPORT_ALL||!EFI64&&!EFIx64) +#define PE32_PLUS_SUPPORT (PE_LOADER_SUPPORT_ALL||EFI64||EFIx64) + +#pragma pack(push) +#pragma pack(2) +//**********************************************************************// +// Structure type definitions for standard PE headers // +//**********************************************************************// +typedef struct _SECTION_HEADER { // Section Header + UINT64 Name; + UINT32 VirtualSize; + UINT32 VirtualAddress; + UINT32 SizeOfRawData; + UINT32 PointerToRawData; + UINT32 Dummy[4]; +} SECTION_HEADER; + +typedef struct _FIXUP_BLOCK{ + UINT32 VirtualAddress; + UINT32 Size; +} FIXUP_BLOCK; + +typedef struct _FIXUP{ + UINT16 Offset : 12, Type: 4; +}FIXUP; + +typedef struct _OPTIONAL_HEADER_CODA { // Optional header coda + UINT32 NumberOfRvaAndSizes; + DIRECTORY_ENTRY Export, Import, Resource, Exception, + Certificate, Reallocations, Debug; +} OPTIONAL_HEADER_CODA; +#pragma pack(pop) + +// Header format for TE images +typedef struct { + UINT16 Signature; + UINT16 Machine; // from the original file header + UINT8 NumberOfSections; // from the original file header + UINT8 Subsystem; // from original optional header + UINT16 StrippedSize; // how many bytes we removed from the header + UINT32 AddressOfEntryPoint; // offset to entry point from original optional header + UINT32 BaseOfCode; // from original image -- required for ITP + UINT64 ImageBase; // from original file header + DIRECTORY_ENTRY DataDirectory[2]; // only base relocation and debug directory +} EFI_TE_IMAGE_HEADER; + +#define EFI_TE_IMAGE_HEADER_SIGNATURE 0x5A56 // TE + +// Data directory indexes in our TE image header +#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC 0 +#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG 1 + +//************************************************************************* +// +// +// Name: IsPeImageValid +// +// Description: +// BOOLEAN IsPeImageValid(IN UINT8 *pstart) reads the header signature of a +// portable executable (PE) image and returns TRUE if it is valid. +// +// Input: +// IN UINT8 *pstart +// Pointer to the start of the PE image. +// +// Output: +// FALSE if image is invalid, otherwise TRUE. +// +// Modified: +// +// Referrals: +// +// Notes: +// If x64_BUILD enabled, supports both PE32 and PE32+. Otherwise only +// supports PE32. +// +// +//************************************************************************* +BOOLEAN IsPeImageValid(UINT8* pstart){ + return + *(UINT16*)pstart == 0x5A4D && //DOS header signature is valid + *(UINT32*)(pstart+=*(UINT32*)(pstart+60)) == 0x00004550 && //PE signature is valid +#if PE_LOADER_SUPPORT_ALL + ( +#endif +#if PE32_SUPPORT + *(UINT16*)(pstart+4) == 0x14c && // IA32 machine + *(UINT16*)(pstart+24) == 0x10b // this is PE32 +#endif +#if PE_LOADER_SUPPORT_ALL + || +#endif +#if PE32_PLUS_SUPPORT + (*(UINT16*)(pstart+4) == 0x200 || *(UINT16*)(pstart+4) == 0x8664)&& // x64 or IA64 machine + *(UINT16*)(pstart+24) == 0x20b // this is PE32+ +#endif +#if PE_LOADER_SUPPORT_ALL + ) +#endif + ; +} + +//************************************************************************* +// +// +// Name: isTeImageValid +// +// Description: +// BOOLEAN isTeImageValid(IN UINT8 *pstart) reads the header signature of a +// terse executable (TE) image and returns true if it is valid. +// +// Input: +// IN UINT8 *pstart +// Pointer to the start of the TE image. +// +// Output: +// FALSE if image is invalid, otherwise TRUE. +// +// Modified: +// +// Referrals: +// +// Notes: +// If x64_BUILD enabled, supports both PE32 and PE32+. Otherwise only +// supports PE32. +// +// +//************************************************************************* +BOOLEAN IsTeImageValid(UINT8* pstart){ + EFI_TE_IMAGE_HEADER *pTe = (EFI_TE_IMAGE_HEADER*)pstart; + return + pTe->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE && //TE signature is valid +#if PE_LOADER_SUPPORT_ALL + ( +#endif +#if PE32_SUPPORT + pTe->Machine == 0x14c // IA32 machine +#endif +#if PE_LOADER_SUPPORT_ALL + || +#endif +#if PE32_PLUS_SUPPORT + (pTe->Machine == 0x200 || pTe->Machine == 0x8664) // x64 or IA64 machine +#endif +#if PE_LOADER_SUPPORT_ALL + ) +#endif + && pTe->StrippedSize >= 2/*MZ signature*/+4/*PE signature*/+ + sizeof(FILE_HEADER)+ + //number of directory entries may vary + sizeof(OPTIONAL_HEADER)-sizeof(DIRECTORY_ENTRY)*7 && + pTe->AddressOfEntryPoint>=pTe->BaseOfCode; +} + +//************************************************************************* +// +// +// Name: PEEntryPoint +// +// Description: +// VOID* PEEntryPoint(IN VOID *p) returns the address of the entry point to +// a portable executable (PE) image. +// +// Input: +// IN VOID *p +// Pointer to the start of the PE image whose entry point is desired. +// +// Output: +// VOID* address to the entry point of the PE image, p. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +VOID* PEEntryPoint(VOID *p) +{ + UINT8 *q = (UINT8*)p; + return q+((OPTIONAL_HEADER*)((FILE_HEADER*)(q+*(UINT32*)(q+60)+4)+1))->AddressOfEntryPoint; +} + +//************************************************************************* +// +// +// Name: TEEntryPoint +// +// Description: +// VOID* TEEntryPoint(IN VOID *p) returns the address of the entry point to +// a terse executable (TE) image. +// +// Input: +// IN VOID *p +// Pointer to the start of the TE image whose entry point is desired. +// +// Output: +// VOID* address to the entry point of the TE image, p. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +VOID* TEEntryPoint(VOID *p) +{ + EFI_TE_IMAGE_HEADER* pTE = (EFI_TE_IMAGE_HEADER*)p; + return (UINT8*)(pTE+1) + pTE->AddressOfEntryPoint - pTE->StrippedSize; +} + +//************************************************************************* +// +// +// Name: GetDebugDirectory +// +// Description: +// DEBUG_DIRECTORY* GetDebugDirectory(IN VOID *ptr, OUT UINTN *TeAdjustment) +// locates and returns the location of DEBUG_DIRECTORY in a terse executable +// (TE) or portable executable (PE) image. +// +// Input: +// IN VOID *ptr +// Pointer to the start of the TE or PE image. +// +// OUT UINTN *TeAdjustment +// If ptr is a valid TE image and not NULL, returns the number of bytes +// stripped from the header. If ptr is a PE image, returns 0. +// +// Output: +// DEBUG_DIRECTORY* address to the image's DEBUG_DIRECTORY structure. +// +// Modified: +// +// Referrals: +// IsTeImageValid +// +// Notes: +// +// +//************************************************************************* +DEBUG_DIRECTORY* GetDebugDirectory(VOID *ptr, UINTN *TeAdjustment) +{ + FILE_HEADER *pFileHeader; + OPTIONAL_HEADER* pOptHeader; + UINT8 *p = (UINT8*)ptr; + OPTIONAL_HEADER_CODA *pCoda; + if (IsTeImageValid(ptr)) + { + EFI_TE_IMAGE_HEADER* pTE = (EFI_TE_IMAGE_HEADER*)p; + UINT32 DebugDirectoryOffset = pTE->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + if (DebugDirectoryOffset == 0) return NULL; + if (TeAdjustment) *TeAdjustment=sizeof(*pTE)-pTE->StrippedSize; + return (DEBUG_DIRECTORY*)((UINT8*)(pTE+1) + DebugDirectoryOffset - pTE->StrippedSize); + } + pFileHeader = (FILE_HEADER*)(p+*(UINT32*)(p+60)+4); + pOptHeader= (OPTIONAL_HEADER*)(pFileHeader+1); +#if PE_LOADER_SUPPORT_ALL + if (pOptHeader->Magic == 0x10b) + {//PE32 + pCoda = (OPTIONAL_HEADER_CODA*)((UINT8*)pOptHeader+92); + } + else + {//PE32+ + pCoda = (OPTIONAL_HEADER_CODA*)((UINT8*)pOptHeader+108); + } +#else + pCoda = (OPTIONAL_HEADER_CODA*)&pOptHeader->NumberOfRvaAndSizes; +#endif + if (pCoda->NumberOfRvaAndSizes<(UINT32)(&pCoda->Debug - &pCoda->Export)) + return NULL; + if (pCoda->Debug.VirtualAddress >= pOptHeader->SizeOfImage) return NULL; + if (TeAdjustment) *TeAdjustment=0; + return (DEBUG_DIRECTORY*)(p + pCoda->Debug.VirtualAddress); +} + +//************************************************************************* +// +// +// Name: GetImageSize +// +// Description: +// UINT32 GetImageSize(IN VOID *p) retrieves the size of a terse executable +// (TE) image or portable executable (PE) image. +// +// Input: +// IN VOID *p +// Pointer to the start of the TE or PE image. +// +// Output: +// UINT32 size of the image. +// +// Modified: +// +// Referrals: +// GetDebugDirectory +// +// Notes: +// +// +//************************************************************************* +UINT32 GetImageSize(VOID *p) +{ + UINT8 *q = (UINT8*)p; + UINT32 Size = ((OPTIONAL_HEADER*)((FILE_HEADER*)(q+*(UINT32*)(q+60)+4)+1))->SizeOfImage; +#ifdef EFI_DEBUG +{ + //ITP Support + DEBUG_DIRECTORY *pDebug = GetDebugDirectory(q,NULL); + if (pDebug /*&& !pDebug->AddressOfRawData*/ && pDebug->PointerToRawData) + Size+=pDebug->SizeOfData; +} +#endif + return Size; +} + +//************************************************************************* +// +// +// Name: GetPeOptionalHeader +// +// Description: +// OPTIONAL_HEADER* GetPeOptionalHeader(IN VOID *p) returns the address of a +// portable executable (PE) image's optional header. +// +// Input: +// IN VOID *p +// Pointer to the start of the PE image whose optional header is desired. +// +// Output: +// OPTIONAL_HEADER* address to the PE image's optional header. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +OPTIONAL_HEADER* GetPeOptionalHeader(VOID *p) +{ + UINT8 *q = (UINT8*)p; + return (OPTIONAL_HEADER*)((FILE_HEADER*)(q+*(UINT32*)(q+60)+4)+1); +} + +//************************************************************************* +// +// +// Name: GetName +// +// Description: +// BOOLEAN GetName(IN UINT8 *p, OUT CHAR8 *sName) retrieves the name of +// portable executable (PE) or terse executable (TE) image, if it is +// available. +// +// Input: +// IN UINT8 *p +// Pointer to the start of the PE or TE image whose name is desired. +// +// OUT CHAR8 *sName +// Returns string containing image's name, if it is available. User is +// responsible for allocating the necessary memory resources. +// +// Output: +// TRUE, if name is located; otherwise FALSE. +// +// Modified: +// +// Referrals: +// GetDebugDirectory +// Strlen +// Strcmp +// MemCpy +// +// Notes: +// +// +//************************************************************************* +BOOLEAN GetName(UINT8 *p, CHAR8 *sName) +{ + UINTN TeAdjustment; + DEBUG_DIRECTORY *pDebug=GetDebugDirectory(p,&TeAdjustment); + UINT32 sig; + UINTN length; + CHAR8 *s, *q, *CvEntry; + if (!pDebug||pDebug->Type!=2) return FALSE; + CvEntry = (CHAR8*)(p+pDebug->AddressOfRawData+TeAdjustment); + sig = *(UINT32*)CvEntry; + if (sig==('N'+('B'<<8)+(('1'+('0'<<8))<<16))) //NB10 + s = CvEntry + 0x10; + else if (sig==('R'+('S'<<8)+(('D'+('S'<<8))<<16))) //RSDS + s = CvEntry + 0x18; + else return FALSE; + length = Strlen(s); + if (length<5 || Strcmp(&s[length-4],".pdb")) return FALSE; + for(q = &s[length-5]; q>=s && *q!='\\'; q--); + q++; + length = s+length-4-q; + MemCpy(sName,q,length); + sName[length]=0; + return TRUE; +} + +//************************************************************************* +// +// +// Name: ReallocatePeImage +// +// Description: +// BOOLEAN ReallocatePeImage(IN UINT8 *pcurrent, IN UINT8 *pnew, +// IN UINT8 *prealloc) loads an already loaded portable executable (PE) image +// at a new memory location with the proper fixup. +// +// Input: +// IN UINT8 *pcurrent +// Pointer to the current location of the PE image in memory. +// +// IN UINT8 *pnew +// Pointer to the new location of the PE image in memory. May be set to the +// same value as pcurrent to adjust fixup only. +// +// IN UINT8 *prealloc +// Pointer to an array of UINTN fixup reallocations. May be set to NULL. +// +// Output: +// FALSE if image contains an unknown fixup type; otherwise TRUE. +// +// Modified: +// +// Referrals: +// GetPeOptionalHeader +// +// Notes: +// Can only handle the IA32 or IA64 fix up types. +// +// +//************************************************************************* +BOOLEAN ReallocatePeImage(UINT8 *pcurrent, UINT8 *pnew, UINT8 *prealloc) +{ + // Fix up + // There is a lot of fix up types but we can handle only IA32 or IA64 specific fix up types. + OPTIONAL_HEADER* pOptHeader = GetPeOptionalHeader(pcurrent); + OPTIONAL_HEADER_CODA *pCoda; + UINT64 ImageBase; + UINT64 Delta; + FIXUP_BLOCK *pBegin, *pEnd; + UINTN *pReallocations = (UINTN*)prealloc; +#if PE_LOADER_SUPPORT_ALL + if (pOptHeader->Magic == 0x10b) + {//PE32 + pCoda = (OPTIONAL_HEADER_CODA*)((UINT8*)pOptHeader+92); + ImageBase = *(UINT32*)((UINT8*)pOptHeader+28); + *(UINT32*)((UINT8*)pOptHeader+28)=(UINT32)pnew; + } + else + {//PE32+ + pCoda = (OPTIONAL_HEADER_CODA*)((UINT8*)pOptHeader+108); + ImageBase = *(UINT64*)((UINT8*)pOptHeader+24); + *(UINT64*)((UINT8*)pOptHeader+24)=(UINT64)(UINTN)pnew; + } +#else + pCoda = (OPTIONAL_HEADER_CODA*)&pOptHeader->NumberOfRvaAndSizes; + ImageBase = pOptHeader->ImageBase; + pOptHeader->ImageBase=(UINTN)pnew; +#endif + Delta = (UINT64)(UINTN)pnew-ImageBase; + if (!Delta) return TRUE; + pBegin = (FIXUP_BLOCK*)(pcurrent+pCoda->Reallocations.VirtualAddress); + pEnd = (FIXUP_BLOCK*)((UINT8*)pBegin + pCoda->Reallocations.Size); + while(pBeginSize) return FALSE; + pFixupInfo = (FIXUP*)(pBegin+1); + pEndOfBlock = (FIXUP*)((UINT8*)pBegin+pBegin->Size); + pFixupPage = pcurrent + pBegin->VirtualAddress; + for(;pFixupInfoOffset); + switch (pFixupInfo->Type){ +#if PE32_SUPPORT + case 3://IMAGE_REL_BASED_HIGHLOW + if (!pReallocations || *pReallocations++ == *pFixup) *pFixup += (UINTN)Delta; + break; +#endif +#if PE32_PLUS_SUPPORT + case 10://IMAGE_REL_BASED_DIR64: + { +#if EFI64 + if ((UINT64)pFixup&0x7){ + UINT8 *p; + UINT32 i; + UINT64 R; + p = (UINT8*)&R; + for(i=0;i<8;i++) p[i]=((UINT8*)pFixup)[i]; + if (!Pred || Pred((UINTN)R)) + { + R+=Delta; + for(i=0;i<8;i++) ((UINT8*)pFixup)[i]=p[i]; + } + }else +#endif + if (!pReallocations || *pReallocations++ == *pFixup) *(UINT64*)pFixup += Delta; + break; + } +#endif + case 0://IMAGE_REL_BASED_ABSOLUTE: + break; + default://Error: Unknown fixup type + return FALSE; + }//switch + }//for + pBegin=(FIXUP_BLOCK*)pEndOfBlock; + }//while + return TRUE; +} + +//************************************************************************* +// +// +// Name: LoadPeImageEx +// +// Description: +// VOID* LoadPeImageEx(IN UINT8 *pold, IN UINT8 *pnew, IN UINT8 *prealloc) +// loads a portal executable into memory from a file. +// +// Input: +// IN UINT8 *pold +// Pointer to the start of the file in memory. +// +// IN UINT8 *pnew +// Pointer to starting location in memory for the loaded image. +// +// IN UINT8 *prealloc +// Pointer to an array of UINTN fixup reallocations. May be set to NULL. +// +// Output: +// If successful, VOID* address of the entry point for the newly loaded +// image; otherwise, NULL if pold and or pnew are not 16-byte aligned, or +// pold does not point to valid PE image. +// +// Modified: +// +// Referrals: +// IsPeImageValid +// MemCpy +// MemSet +// ReallocatePeImage +// GetDebugDirectory +// +// Notes: +// +// +//************************************************************************* +VOID* LoadPeImageEx(UINT8* pold, UINT8* pnew, UINT8 *prealloc){ + FILE_HEADER *pFileHeader; + OPTIONAL_HEADER* pOptHeader; + SECTION_HEADER *pSection; + UINT8 *p; + UINT32 i; +#ifdef EFI64 + // Destination and source buffers should starts at the 16-byte boundary + if ((int)pnew&0xf || (int)pold&0xf) return NULL; +#endif + if (!IsPeImageValid(pold)) return NULL; + pFileHeader = (FILE_HEADER*)(pold+*(UINT32*)(pold+60)+4); + pOptHeader= (OPTIONAL_HEADER*)(pFileHeader+1); + // Sections should have at least sizeof(INTN)-byte alignment + if (pOptHeader->SectionAlignmentOptionalHeaderSize); + // copy headers + MemCpy(pnew,pold,pOptHeader->SizeOfHeaders); + //copy sections + // in the file image pSection->PointerToRawData contains offset of the section data + // in the memory image the section data should be placed at pSection->VirtualAddress RVA. + p=pnew+pOptHeader->SizeOfHeaders; + for(i=0;iNumberOfSections;i++,pSection++){ + // fill with zeros am empty space between sections + MemSet(p,pnew+pSection->VirtualAddress-p,0); + p=pnew+pSection->VirtualAddress; + if (pSection->PointerToRawData){ + UINTN SectionSize = (pSection->VirtualSizeSizeOfRawData)?pSection->VirtualSize:pSection->SizeOfRawData; + MemCpy( + pnew+pSection->VirtualAddress, + pold+pSection->PointerToRawData, + SectionSize + ); + p+=SectionSize; + } + } + //align the last section + MemSet(p,pnew+pOptHeader->SizeOfImage-p,0); + // Fix up + if (!ReallocatePeImage(pnew, pnew, prealloc)) return NULL; +#ifdef EFI_DEBUG +{ + //ITP Support + DEBUG_DIRECTORY *pDebug = GetDebugDirectory(pnew,NULL); + if (pDebug /*&& !pDebug->AddressOfRawData*/ && pDebug->PointerToRawData) + { + MemCpy(pnew+pOptHeader->SizeOfImage,pold+pDebug->PointerToRawData,pDebug->SizeOfData); + pDebug->AddressOfRawData = pOptHeader->SizeOfImage; + } +} +#endif + return pnew+pOptHeader->AddressOfEntryPoint; +} + +//************************************************************************* +// +// +// Name: LoadPeImage +// +// Description: +// VOID* LoadPeImage(IN UINT8 *pold, IN UINT8 *pnew) is a wrapper function +// for LoadPeImageEx which passes NULL for prealloc. +// +// Input: +// IN UINT8 *pold +// Pointer to the start of the file in memory. +// +// IN UINT8 *pnew +// Pointer to starting location in memory for the loaded image. +// +// Output: +// If successful, VOID* address of the entry point for the newly loaded +// image; otherwise, NULL if pold and or pnew are not 16-byte aligned, or +// pold does not point to valid PE image. +// +// Modified: +// +// Referrals: +// LoadPeImageEx +// +// Notes: +// +// +//************************************************************************* +VOID* LoadPeImage(UINT8* pold, UINT8* pnew){ + return LoadPeImageEx(pold,pnew,NULL); +} + +//************************************************************************* +// +// +// Name: FindPeSection +// +// Description: +// VOID* FindPeSection(IN UINT8 *pstart, IN UINT64 name, OUT UINTN *pSize) +// locates a section with the user provided name inside a portable executable +// (PE) image. +// +// Input: +// IN UINT8 *pstart +// Pointer to the start of the image to be searched. +// +// IN UINT64 name +// UINT64 name associated with the section to be located. +// +// OUT UINTN *pSize +// Contains the size of the located section. +// +// Output: +// If located, VOID* pointer to the virtual address of the located section; +// otherwise, NULL. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +VOID* FindPeSection(UINT8* pstart, UINT64 name, UINTN* pSize){ + FILE_HEADER *pFileHeader = (FILE_HEADER*)(pstart+*(UINT32*)(pstart+60)+4); + SECTION_HEADER *pSection = (SECTION_HEADER*)((UINT8*)(pFileHeader+1)+pFileHeader->OptionalHeaderSize); + UINT32 i; + for(i=0;iNumberOfSections;i++,pSection++){ + if (pSection->Name!=name) continue; + if (pSize) *pSize = pSection->VirtualSize; + return pstart+pSection->VirtualAddress; + } + return NULL; +} +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Library/PeiLib.c b/Library/PeiLib.c new file mode 100644 index 0000000..c3f859e --- /dev/null +++ b/Library/PeiLib.c @@ -0,0 +1,1132 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//************************************************************************* +// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Library/PeiLib.c 1 4/16/14 3:10a Chaseliu $ +// +// $Revision: 1 $ +// +// $Date: 4/16/14 3:10a $ +//************************************************************************* +// Revision History +// ---------------- +// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Library/PeiLib.c $ +// +// 1 4/16/14 3:10a Chaseliu +// [TAG] EIP163569 +// [Category] Improvement +// [Description] Update for support 2014 BIOS Security Disclosures. +// [Files] +// Library\PeiLib.c +// Library\EfiLib.c +// Core\EM\NVRAM\NVRAMDXE.c +// Core\EM\Capsule2_0\Capsule2_0.c +// Core\CORE_DXE\FwVolBlock.c +// +// 29 2/28/14 5:41p Artems +// EIP 154195 Fixed vulnerability where memory pointer was stored in NVRaM +// and may be compromised +// +// 27 8/12/11 12:25p Artems +// EIP 64107: Added changes for module to be compliant with PI +// specification v 1.2 +// +// 26 5/27/11 5:59p Felixp +// PeiGetNextVariableName is updated: +// The GetNextVariableName function has been renamed to NextVariableName +// to comply with the specification. +// +// 25 2/05/11 3:14p Artems +// Added compatibility functions to work in both PI 0.91 and PI 1.0 +// versions +// +// 24 11/05/10 2:47p Artems +// EIP 44635 - removed commented out string +// +// 23 10/12/10 5:15p Artems +// EIP 44635 Added token MAX_PEI_PERF_LOG_ENTRIES +// +// 22 11/25/09 1:32p Felixp +// PeiTrace functions is updated to suppress Trace message +// if message Level defined by the first parameter is disabled using +// TRACE_LEVEL_MASK SDL token. +// +// 21 7/30/09 4:45p Vyacheslava +// Fixed comments. +// +// 20 7/28/09 4:55p Vyacheslava +// Minor bug fix. EIP#24453: Synopsis: CPU exception when printing long +// debug messages. +// +// 19 7/10/09 3:49p Felixp +// Function headers added +// +// 18 6/06/08 10:54a Felixp +// SaveS3PerformanceData routine added +// +// 17 5/07/08 12:22p Felixp +// Performance API added +// +// 16 10/22/07 6:24p Felixp +// FindFfsFileByName routine added. +// +// 15 8/30/07 11:01p Felixp +// PeiGetVariable and PeiGetNextVariableName routines added. +// +// 14 3/13/07 1:40a Felixp +// +// 13 8/24/06 9:27a Felixp +// Preliminary x64 support (work in progress) +// +// 12 3/13/06 1:50a Felixp +// +// 11 12/09/05 2:08p Felixp +// +// 10 10/11/05 2:43p Felixp +// +// 9 10/09/05 8:52p Felixp +// +// 8 10/09/05 4:54p Felixp +// +// 7 10/09/05 4:14p Felixp +// +// 6 10/09/05 11:27a Felixp +// Support for performance measurements added. +// +// 5 6/16/05 10:48a Felixp +// CreateLoadHob function added (used by PEIMs to reguest reallocation to +// RAM, +// once memory is detected) +// +// 3 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 12/23/04 9:42a Felixp +// +// 2 11/10/04 5:16p Felixp +// Level parameter added to PeiTrace fucntion +// +// 1 11/02/04 5:30p Felixp +// +//************************************************************************* +// +// +// Name: PeiLib.c +// +// Description: +// Contains an assortment of localized PEI library functions. +// +// +//************************************************************************* + +#include +#include +#include +#include +#include +#include +#include + +//************************************************************************* +// +// +// Name: PeiTrace +// +// Description: +// VOID PeiTrace(IN UINTN Level, IN EFI_PEI_SERVICES **ppPS, +// IN CHAR8 *sFormat, IN ...) prints a debug message using the +// ReportStatusCode from PEI Services if the specified error level is +// enabled. +// +// Input: +// IN UINTN Level +// The error level of the debug message. +// +// IN EFI_PEI_SERVICES **ppPS +// Double pointer to PEI Services Table. +// +// IN CHAR8 *sFormat +// Format string for the debug message to print. +// +// IN ... +// Additional parameters utilized by the format string. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// PrepareStatusCodeString +// va_start +// va_end +// PEI_TRACE +// Sprintf +// +// Notes: +// Use the PEI_TRACE macro for debug messages in PEI! This allows the +// DEBUG_MODE token to control the inclusion of debug messages. See +// Sprintf function for format string syntax. +// +// +//************************************************************************* + +VOID PeiTrace(UINTN Level, CONST EFI_PEI_SERVICES **ppPS, CHAR8 *sFormat,...) +{ + CHAR8 Buffer[256]; + extern const UINT32 TraceLevelMask; + va_list ArgList; + if ( (Level & TraceLevelMask) == 0 ) return; + ArgList = va_start(ArgList,sFormat); + PrepareStatusCodeString( Buffer, sizeof(Buffer), sFormat, ArgList ); + (*ppPS)->ReportStatusCode ( + (EFI_PEI_SERVICES**)ppPS, EFI_DEBUG_CODE, + EFI_SOFTWARE_UNSPECIFIED, 0, NULL, + (EFI_STATUS_CODE_DATA *)Buffer + ); + va_end(ArgList); +} + +//************************************************************************* +// +// +// Name: CreateHobMemoryAllocationModule +// +// Description: +// EFI_STATUS CreateHobMemoryAllocationModule( +// IN EFI_PEI_SERVICES **PeiServices, +// IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress, IN UINT64 MemoryLength, +// IN EFI_MEMORY_TYPE MemoryType, IN EFI_GUID *ModuleName, +// IN EFI_PHYSICAL_ADDRESS EntryPoint) adds a memory allocation HOB with a +// memory allocation module GUID using CreateHob from PEI Services. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// Double pointer to PEI Services Table. +// +// IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress +// The physical address of the module. +// +// IN UINT64 MemoryLength +// The length of the module in bytes. +// +// IN EFI_MEMORY_TYPE MemoryType +// Module memory type. +// +// IN EFI_GUID *ModuleName +// The GUID File Name of the module. +// +// IN EFI_PHYSICAL_ADDRESS EntryPoint +// The 64-bit physical address of the module's entry point. +// +// Output: +// EFI_INVALID_PARAMETER, if Hob = NULL. +// EFI_OUT_OF_RESOURCES, if there is not enough space to create HOB. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS CreateHobMemoryAllocationModule( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress, + IN UINT64 MemoryLength, IN EFI_MEMORY_TYPE MemoryType, + IN EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS EntryPoint +) +{ + static EFI_GUID gHobMemAllocModGuid=EFI_HOB_MEMORY_ALLOC_MODULE_GUID; + EFI_STATUS Status; + EFI_HOB_MEMORY_ALLOCATION_MODULE *MemAllocModHob; + + Status = (*PeiServices)->CreateHob( + PeiServices, + EFI_HOB_TYPE_MEMORY_ALLOCATION, + sizeof(EFI_HOB_MEMORY_ALLOCATION_MODULE), + &MemAllocModHob); + if (Status != EFI_SUCCESS) return Status; + MemAllocModHob->MemoryAllocationHeader.Name=gHobMemAllocModGuid; + MemAllocModHob->MemoryAllocationHeader.MemoryBaseAddress=MemoryBaseAddress; + MemAllocModHob->MemoryAllocationHeader.MemoryLength=MemoryLength; + MemAllocModHob->MemoryAllocationHeader.MemoryType=MemoryType; + *(UINT32*)&MemAllocModHob->MemoryAllocationHeader.Reserved=0; + MemAllocModHob->ModuleName=*ModuleName; + MemAllocModHob->EntryPoint=EntryPoint; + return EFI_SUCCESS; +} + +//************************************************************************* +// +// +// Name: CreateHobResourceDescriptor +// +// Description: +// EFI_STATUS CreateHobResourceDescriptor(IN EFI_PEI_SERVICES **PeiServices, +// IN EFI_GUID *Owner, IN EFI_RESOURCE_TYPE ResourceType, +// IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, +// IN EFI_PHYSICAL_ADDRESS PhysicalStart, IN UINT64 ResourceLength) builds a +// resource descriptor HOB that describes a chunk of system memory using +// CreateHob from PEI Services. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// Double pointer to the PEI Services Table. +// +// IN EFI_GUID *Owner +// GUID of the owner of this resource. Make this NULL if there is none. +// +// IN EFI_RESOURCE_TYPE ResourceType +// The type of resource described by this HOB. +// +// IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute +// The resource attributes of the memory described by this HOB. +// +// IN EFI_PHYSICAL_ADDRESS PhysicalStart +// The 64-bit physical address of memory described by this HOB. +// +// IN UINT64 ResourceLength +// The length of the memory described by this HOB in bytes. +// +// Output: +// EFI_INVALID_PARAMETER, if HOB = NULL. +// EFI_OUT_OF_RESOURCES, if there is not enough space to create HOB. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS CreateHobResourceDescriptor +( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_GUID *Owner, IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 ResourceLength +) +{ + EFI_STATUS Status; + EFI_HOB_RESOURCE_DESCRIPTOR *ResHob; + + Status = (*PeiServices)->CreateHob( + PeiServices, + EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, + sizeof(EFI_HOB_RESOURCE_DESCRIPTOR), + &ResHob); + if (Status != EFI_SUCCESS) return Status; + + ResHob->Owner=*Owner; + ResHob->ResourceType=ResourceType; + ResHob->ResourceAttribute=ResourceAttribute; + ResHob->PhysicalStart=PhysicalStart; + ResHob->ResourceLength=ResourceLength; + return EFI_SUCCESS; +} + +//************************************************************************* +// +// +// Name: CreateLoadHob +// +// Description: +// EFI_STATUS CreateLoadHob(IN EFI_PEI_SERVICES **ppPS, +// IN EFI_FFS_FILE_HEADER *pFfsHeader, EFI_PEIM_ENTRY_POINT EntryPoint, +// EFI_PEIM_ENTRY_POINT InMemEntryPoint) builds a EFI_HOB_TYPE_GUID_EXTENSION +// HOB with a PEIM load HOB. +// +// Input: +// IN EFI_PEI_SERVICES **ppPS +// Double pointer to the PEI Services Table. +// +// IN EFI_FFS_FILE_HEADER *pFfsHeader +// Pointer to the desired FFS header. +// +// EFI_PEIM_ENTRY_POINT EntryPoint +// Pointer to the FFS entry point. +// +// EFI_PEIM_ENTRY_POINT InMemEntryPoint +// Pointer to the FFS entry point in memory. +// +// Output: +// EFI_INVALID_PARAMETER, if HOB = NULL. +// EFI_OUT_OF_RESOURCES, if not enough space to create HOB. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +EFI_STATUS CreateLoadHob( + IN EFI_PEI_SERVICES **ppPS, IN EFI_FFS_FILE_HEADER *pFfsHeader, + EFI_PEIM_ENTRY_POINT EntryPoint, EFI_PEIM_ENTRY_POINT InMemEntryPoint +) +{ + EFI_STATUS Status; + PEIM_LOAD_HOB *pHob; + static EFI_GUID guidAmiPeimLoadHob = AMI_PEIM_LOAD_HOB_GUID; + + Status=(*ppPS)->CreateHob(ppPS, EFI_HOB_TYPE_GUID_EXTENSION, sizeof(PEIM_LOAD_HOB),&pHob); + if (!EFI_ERROR(Status)) + { + pHob->Header.Name = guidAmiPeimLoadHob; + pHob->pFfsHeader = pFfsHeader; + pHob->EntryPoint = EntryPoint; + pHob->InMemEntryPoint= InMemEntryPoint; + } + return Status; +} + +//************************************************************************* +// +// +// Name: PeiGetVariable +// +// Description: +// EFI_STATUS PeiGetNextVariableName(IN EFI_PEI_SERVICES **PeiServices, +// IN CONST CHAR16 *VariableName, IN CONST EFI_GUID *VariableGuid, +// OUT UINT32 *Attributes, IN OUT UINTN *DataSize, OUT VOID *Data) reads an +// EFI variable; it serves as a wrapper for the Read Only Variable PPI +// GetVariable routine. The functions first locates the Read Only Variable +// PPI instance, then makes a call to the GetVariable routine and returns +// the EFI_STATUS of the GetVariable call. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// Double pointer to the PEI Services Table. +// +// IN CONST CHAR16 *VariableName +// A pointer to a null-terminated string that is the variable's name. +// +// IN CONST EFI_GUID *VariableGuid +// A pointer to an EFI_GUID that is the variable's GUID. The combination of +// VariableGuid and VariableName must be unique. +// +// OUT UINT32 *Attributes +// If non-NULL, on return, points to the variable's attributes. +// +// IN OUT UINTN *DataSize +// On entry, points to the size in bytes of the Data buffer. On return, +// points to the size of the data returned in Data. +// +// OUT VOID *Data +// Points to the buffer which will hold the returned variable value. The +// user is responsible for allocating this memory! +// +// Output: +// EFI_BUFFER_TOO_SMALL, if DataSize is too small to hold the contents of +// the variable. DataSize will be set to show the +// minimum required size. +// EFI_INVALID_PARAMETER, if VariableName, VariableGuid, DataSize, or Data +// are equal to NULL. +// EFI_DEVICE_ERROR, if variable could not be retrieved because of a +// device error. +// EFI_NOT_FOUND, if the variable or Read Only Variable PPI could +// not be found. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// +// Notes: +// See Platform Initialization Specification for details regarding the +// Read Only Variable PPI and GetVariable. +// +// +//************************************************************************* +EFI_STATUS PeiGetVariable( + IN EFI_PEI_SERVICES **PeiServices, + IN CONST CHAR16 *VariableName, IN CONST EFI_GUID *VariableGuid, + OUT UINT32 *Attributes, + IN OUT UINTN *DataSize, OUT VOID *Data +) +{ + EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariablePpi; + EFI_STATUS Status = (*PeiServices)->LocatePpi( + PeiServices, &gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, &VariablePpi + ); + if (EFI_ERROR(Status)) return Status; + return VariablePpi->GetVariable( + VariablePpi,VariableName, VariableGuid, Attributes, DataSize, Data + ); +} + +//************************************************************************* +// +// +// Name: PeiGetNextVariableName +// +// Description: +// EFI_STATUS PeiGetNextVariableName(IN EFI_PEI_SERVICES **PeiServices, +// IN OUT UINTN *VariableNameSize, IN OUT CHAR16 *VariableName, +// IN OUT EFI_GUID *VariableGuid) performs enumeration of the EFI variables. +// This function serves as a wrapper for the Read Only Variable PPI +// GetNextVariableName routine. It locates the Read Only Variable PPI +// instance, then makes a call to the GetNextVariableName routine and returns +// its EFI_STATUS. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// Double pointer to the PEI Services Table. +// +// IN OUT UINTN *VariableNameSize +// On entry, points to the size of the buffer pointed to by VariableName. +// If function returns EFI_BUFFER_TOO_SMALL, VariableNameSize is updated to +// reflect the buffer size required for the next variable's name. +// +// IN OUT CHAR16 *VariableName +// On entry, a pointer to a null-terminated string that is the variable's +// name. On return, points to the next variable's null-terminated name +// string. +// +// IN OUT EFI_GUID *VariableGuid +// On entry, a pointer to an UEFI _GUID that is the variable's GUID. On +// return, a pointer to the next variable's GUID. +// +// Output: +// EFI_NOT_FOUND, if the variable or Read Only Variable PPI could +// not be found. +// EFI_BUFFER_TOO_SMALL, if VariableNameSize is too small for the resulting +// data. VariableNameSize is updated with the size +// required for the specified variable. +// EFI_INVALID_PARAMETER, if VariableName, VariableNameSize, or VariableGuid +// are NULL. +// EFI_DEVICE_ERROR, if the variable could not be retrieved because of +// a device error. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// +// Notes: +// See the Platform Initialization Specification for details regarding +// the Read Only Variable PPI and NextVariableName. +// +// +//************************************************************************* +EFI_STATUS PeiGetNextVariableName( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT UINTN *VariableNameSize, IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VariableGuid +) +{ + EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariablePpi; + EFI_STATUS Status = (*PeiServices)->LocatePpi( + PeiServices, &gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, &VariablePpi + ); + if (EFI_ERROR(Status)) return Status; + return VariablePpi->NextVariableName( + VariablePpi,VariableNameSize, VariableName, VariableGuid + ); +} + +//************************************************************************* +// +// +// Name: FindFfsFileByName +// +// Description: +// VOID* FindFfsFileByName(IN EFI_PEI_SERVICES **PeiServices, +// IN EFI_FV_FILETYPE FileType, IN EFI_GUID *FileName) scans all available +// firmware volumes for a FFS file of type FileType with GUID equal to +// FileName and returns the address of the first byte of the FFS file data. +// If more than one file matches the criteria, the function returns the +// address of the first file found. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// Double pointer to the PEI Services Table. +// +// IN EFI_FV_FILETYPE FileType +// Type of FFS file to find. +// +// IN EFI_GUID *FileName +// GUID of FFS file to find. +// +// Output: +// VOID* pointer to the first byte of the FFS file data. Returns NULL if no +// FFS file found. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +VOID* FindFfsFileByName( + IN EFI_PEI_SERVICES **PeiServices, EFI_FV_FILETYPE FileType, + EFI_GUID *FileName +){ + EFI_FIRMWARE_VOLUME_HEADER* pFV; + UINTN FvNum=0; + //loop over all FV + while( !EFI_ERROR ((*PeiServices)->FfsFindNextVolume (PeiServices, FvNum++, &pFV) ) ){ + EFI_FFS_FILE_HEADER* pFile = NULL; + EFI_STATUS Status; + // loop over raw files within FV + while(TRUE){ + Status = (*PeiServices)->FfsFindNextFile(PeiServices, FileType, pFV, &pFile); + if( EFI_ERROR(Status) ) break; + //make sure this is our RAW file. + //guidcmp works like strcmp. It returns 0 when GUIDs are the same. + if (guidcmp(&pFile->Name,&FileName)) continue; + //skip file header + return pFile+1; + } + } + return NULL; +} + +//**************************************************************************** +// PERFORMANCE MEASUREMENT DEFINITIONS +//**************************************************************************** +static EFI_GUID gEfiPeiPerformanceHobGuid = EFI_PEI_PERFORMANCE_HOB_GUID; + +#define EFI_PERF_PEI_ENTRY_MAX_NUM 50 + +typedef struct { + CHAR8 Token[EFI_PERF_PDBFILENAME_LENGTH]; + UINT32 Duration; +} EFI_PERF_DATA; + +typedef struct { + UINT64 BootToOs; + UINT64 S3Resume; + UINT32 S3EntryNum; + EFI_PERF_DATA S3Entry[EFI_PERF_PEI_ENTRY_MAX_NUM]; + UINT64 CpuFreq; + UINT64 BDSRaw; + UINT32 Count; + UINT32 Signiture; +} EFI_PERF_HEADER; + +//************************************************************************* +// +// +// Name: PEI_PERF_START +// +// Description: +// PEI_PERF_START(Ps, Token, FileHeader, Value) is a macro which invokes +// the PeiPerfMeasure function to log a timer entry for measuring performance +// if the PEI_PERFORMANCE SDL token is turned on. If the PEI_PERFORMANCE SDL +// token is turned off, the macro does nothing. +// +// Input: +// IN EFI_PEI_SERVICES **Ps +// Double pointer to the PEI Services Table. +// +// IN CHAR16 *Token +// Pointer to token name. +// +// IN EFI_FFS_FILE_HEADER *FileHeader +// Pointer to the file header. +// +// IN UINT64 Value +// A non-zero value indicates the start time. Otherwise, GetCpuTimer is used +// to get the current CPU timer value. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// PeiPerfMeasure +// GetCpuTimer +// +// Notes: +// This macro is defined in AmiPeiLib.h. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: PEI_PERF_END +// +// Description: +// PEI_PERF_END(Ps, Token, FileHeader, Value) is a macro which invokes +// the PeiPerfMeasure function to stop timing for an entry to determine +// performance if the PEI_PERFORMANCE SDL token is turned on. If the +// PEI_PERFORMANCE SDL token is turned off, the macro does nothing. +// +// Input: +// IN EFI_PEI_SERVICES **Ps +// Double pointer to the PEI Services Table. +// +// IN CHAR16 *Token +// Pointer to token name. +// +// IN EFI_FFS_FILE_HEADER *FileHeader +// Pointer to the file header. +// +// IN UINT64 Value +// A non-zero value indicates the stop time. Otherwise, GetCpuTimer is used +// to get the current CPU timer value. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// PeiPerfMeasure +// GetCpuTimer +// +// Notes: +// This macro is defined in AmiPeiLib.h. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: PEI_PERF_SAVE_S3_DATA +// +// Description: +// PEI_PERF_SAVE_S3_DATA(Ps) is a macro which invokes the +// SaveS3PerformanceData function in order to save the S3 performance data in +// an EFI PEI performance HOB. This should only be called once, just before +// the end of PEI. +// +// Input: +// IN EFI_PEI_SERVICES **Ps +// Double pointer to the PEI Services Table. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// SaveS3PerformanceData +// +// Notes: +// This macro is defined in AmiPeiLib.h. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: PeiPerfMeasure +// +// Description: +// VOID PeiPerfMeasure(IN EFI_PEI_SERVICES **PeiServices, IN CHAR16 *Token, +// IN EFI_FFS_FILE_HEADER *FileHeader, IN BOOLEAN EntryExit, IN UINT64 Value) +// logs a timestamp count for measuring performance. See the notes for +// proper usage. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// Double pointer to the PEI Services Table. +// +// IN CHAR16 *Token +// Pointer to token name. +// +// IN EFI_FFS_FILE_HEADER *FileHeader +// Pointer to the file header. +// +// IN BOOLEAN EntryExit +// FALSE indicates start, TRUE indicates stop. +// +// IN UINT64 Value +// If EntryExit is TRUE, a non-zero value indicates stop time. Otherwise if +// EntryExit is FALSE, a non-zero value indicates start time. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// GetCpuTimer +// +// Notes: +// Use the PEI_PERF_START and PEI_PERF_END macros; this allows performance +// monitoring to be enabled or disabled with the PEI_PERFORMANCE SDL token. +// +// +//************************************************************************* +VOID PeiPerfMeasure ( + EFI_PEI_SERVICES **PeiServices, + IN CHAR16 *Token, IN EFI_FFS_FILE_HEADER *FileHeader, + IN BOOLEAN EntryExit, IN UINT64 Value +) +{ + EFI_STATUS Status; + EFI_HOB_GUID_TYPE *Hob; + EFI_HOB_GUID_DATA_PERFORMANCE_LOG *PerfHobData; + PEI_PERFORMANCE_MEASURE_LOG_ENTRY *Log; + EFI_PEI_PPI_DESCRIPTOR *PerfHobDescriptor; + UINT64 TimeCount; + UINTN Index; + UINTN Index2; + EFI_GUID *Guid; + EFI_GUID *CheckGuid; + + TimeCount = 0; + // + // Get the END time as early as possible to make it more accurate. + // + if (EntryExit) { + TimeCount = GetCpuTimer(); + } + + // + // Locate the Pei Performance Log Hob. + // + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gEfiPeiPerformanceHobGuid, + 0, + &PerfHobDescriptor, + NULL + ); + + // + // If the Performance Hob was not found, build and install one. + // + if (EFI_ERROR(Status)) { + Status = (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_GUID_EXTENSION, + sizeof (EFI_HOB_GUID_TYPE) + + sizeof(EFI_HOB_GUID_DATA_PERFORMANCE_LOG) + + (MAX_PEI_PERF_LOG_ENTRIES-1) * sizeof(PEI_PERFORMANCE_MEASURE_LOG_ENTRY) + + sizeof(EFI_PEI_PPI_DESCRIPTOR), + &Hob + ); + ASSERT_PEI_ERROR(PeiServices, Status); + Hob->Name = gEfiPeiPerformanceHobGuid; + PerfHobData = (EFI_HOB_GUID_DATA_PERFORMANCE_LOG *)(Hob+1); + PerfHobData->NumberOfEntries = 0; + PerfHobDescriptor = (EFI_PEI_PPI_DESCRIPTOR *)((UINT8 *)(PerfHobData+1) + + (sizeof(PEI_PERFORMANCE_MEASURE_LOG_ENTRY) * + (MAX_PEI_PERF_LOG_ENTRIES-1) + ) + ); + PerfHobDescriptor->Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST); + PerfHobDescriptor->Guid = &gEfiPeiPerformanceHobGuid; + PerfHobDescriptor->Ppi = NULL; + + (*PeiServices)->InstallPpi ( + PeiServices, + PerfHobDescriptor + ); + } + + PerfHobData = (EFI_HOB_GUID_DATA_PERFORMANCE_LOG *)(((UINT8 *)(PerfHobDescriptor)) - + ((sizeof(PEI_PERFORMANCE_MEASURE_LOG_ENTRY) * + (MAX_PEI_PERF_LOG_ENTRIES-1) + ) + + sizeof(EFI_HOB_GUID_DATA_PERFORMANCE_LOG) + ) + ); + + if (PerfHobData->NumberOfEntries >= MAX_PEI_PERF_LOG_ENTRIES) { + return; + } + + if (!EntryExit) { + Log = &(PerfHobData->Log[PerfHobData->NumberOfEntries]); + (*PeiServices)->SetMem (Log, sizeof(PEI_PERFORMANCE_MEASURE_LOG_ENTRY), 0); + + // + // If not NULL pointer, copy the file name + // + if (FileHeader != NULL) { + Log->Name = FileHeader->Name; + } + + // + // Copy the description string + // + (*PeiServices)->CopyMem ( + &(Log->DescriptionString), + Token, + (PEI_PERF_MAX_DESC_STRING-1) * sizeof(UINT16) + ); + + // + // Get the start time as late as possible to make it more accurate. + // + TimeCount = GetCpuTimer(); + + // + // Record the time stamp. + // + if (Value != 0) { + Log->StartTimeCount = Value; + } else { + Log->StartTimeCount = TimeCount; + } + Log->StopTimeCount = 0; + + // + // Increment the number of valid log entries. + // + PerfHobData->NumberOfEntries++; + + } else { + + for (Index = PerfHobData->NumberOfEntries-1; Index >= 0; Index--) { + Log = NULL; + for (Index2 = 0; Index2 < PEI_PERF_MAX_DESC_STRING; Index2++) { + if (PerfHobData->Log[Index].DescriptionString[Index2] == 0) { + Log = &(PerfHobData->Log[Index]); + break; + } + if (PerfHobData->Log[Index].DescriptionString[Index2] != + Token[Index2]) { + break; + } + } + if (Log != NULL) { + if (FileHeader != NULL) { + Guid = &(Log->Name); + CheckGuid = &(FileHeader->Name); + if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) && + (((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) && + (((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) && + (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) { + if (Value != 0) { + Log->StopTimeCount = Value; + } else { + Log->StopTimeCount = TimeCount; + } + break; + } + } else { + if (Value != 0) { + Log->StopTimeCount = Value; + } else { + Log->StopTimeCount = TimeCount; + } + break; + } + } + } + + } + + return; +} + +//************************************************************************* +// +// +// Name: SaveS3PerformanceData +// +// Description: +// VOID SaveS3PerformanceData(IN EFI_PEI_SERVICES **PeiServices) saves the +// S3 performance data in an EFI PEI performance HOB. This should only be +// called once, just before the end of PEI. See notes for proper usage. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// Double pointer to PEI Services Table. +// +// Output: +// VOID. +// +// Modified: +// +// Referrals: +// GetCpuTimer +// +// Notes: +// To use this function properly, use the PEI_PERF_SAVE_S3_DATA macro. This +// allows the PEI_PERFORMANCE SDL token to control enabling and disabling +// performance measurements. +// The PEI_PERF_SAVE_S3_DATA macro is used by S3Resume module to log performance data. +// +// +//************************************************************************* +VOID SaveS3PerformanceData(IN EFI_PEI_SERVICES **PeiServices){ + static EFI_GUID gEfiPeiPerformanceHobGuid = EFI_PEI_PERFORMANCE_HOB_GUID; + EFI_STATUS Status; + UINT64 Time; + UINTN VarSize; + EFI_GUID gEfiGlobalVariableGuid = EFI_GLOBAL_VARIABLE; + EFI_PERF_HEADER *PerfHeader; + EFI_PHYSICAL_ADDRESS AcpiLowMemoryBase; + UINT32 i; + UINT32 j; + EFI_HOB_GUID_DATA_PERFORMANCE_LOG *LogHob; + PEI_PERFORMANCE_MEASURE_LOG_ENTRY *LogEntry; + EFI_PEI_HOB_POINTERS Hob; + + Time = GetCpuTimer(); + VarSize = sizeof (EFI_PHYSICAL_ADDRESS); + Status = PeiGetVariable( + PeiServices, + L"PerfDataMemAddrInternal", &gAmiGlobalVariableGuid, + NULL, &VarSize, &AcpiLowMemoryBase + + ); + if (EFI_ERROR (Status)) return; + + PerfHeader = (EFI_PERF_HEADER *) ((UINT32) AcpiLowMemoryBase); + *((UINT64 *) (&PerfHeader->S3Resume)) = Time; + // Get S3 detailed performance data + PerfHeader->S3EntryNum = 0; + + (*PeiServices)->GetHobList (PeiServices, &Hob.Raw); + Status = FindNextHobByGuid(&gEfiPeiPerformanceHobGuid,&Hob.Raw); + if (EFI_ERROR (Status)) return; + LogHob = (EFI_HOB_GUID_DATA_PERFORMANCE_LOG *) (Hob.Raw + sizeof (EFI_HOB_GENERIC_HEADER) + sizeof (EFI_GUID)); + + for( i = 0; + ((i < LogHob->NumberOfEntries) && (PerfHeader->S3EntryNum < EFI_PERF_PEI_ENTRY_MAX_NUM)); + i++ + ){ + LogEntry = &(LogHob->Log[i]); + if (LogEntry->StopTimeCount == 0) { + continue; + } + for (j = 0; j < 8; j++) { + PerfHeader->S3Entry[PerfHeader->S3EntryNum].Token[j] = (CHAR8) (LogEntry->DescriptionString[j]); + } + PerfHeader->S3Entry[PerfHeader->S3EntryNum].Duration = (UINT32) Div64 ( + LogEntry->StopTimeCount - LogEntry->StartTimeCount, + (UINT32) PerfHeader->CpuFreq, + NULL + ); + PerfHeader->S3EntryNum++; + } +} + +EFI_STATUS PeiLoadFile( + IN CONST EFI_PEI_SERVICES ** PeiServices, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint +){ +#if PI_SPECIFICATION_VERSION < 0x00010000 + EFI_PEI_FV_FILE_LOADER_PPI *Loader; +#else + EFI_PEI_LOAD_FILE_PPI *Loader; + UINT32 AuthenticationState; +#endif; + EFI_PEI_PPI_DESCRIPTOR *Dummy; + EFI_STATUS Status = (*PeiServices)->LocatePpi( + (EFI_PEI_SERVICES**)PeiServices, + &gEfiPeiLoadFilePpiGuid,0, &Dummy, &Loader + ); + if ((EFI_ERROR(Status))) return Status; + return +#if PI_SPECIFICATION_VERSION < 0x00010000 + Status = Loader->FvLoadFile( +#else + Status = Loader->LoadFile( +#endif + Loader, FileHandle, ImageAddress, ImageSize, EntryPoint +#if PI_SPECIFICATION_VERSION >= 0x00010000 + ,&AuthenticationState +#endif + ); +} + +#if PI_SPECIFICATION_VERSION >= 0x00010000 +#pragma pack (1) +typedef struct { + UINT16 Limit; + UINTN Base; +} DESCRIPTOR_TABLE; +#pragma pack() + +VOID CPULib_SaveIdt(DESCRIPTOR_TABLE *Idt); + +EFI_PEI_SERVICES ** GetPeiServicesTablePointer (VOID){ + EFI_PEI_SERVICES **PeiServices; + DESCRIPTOR_TABLE Idtr; + + CPULib_SaveIdt (&Idtr); + PeiServices = (EFI_PEI_SERVICES **) (*(UINTN*)(Idtr.Base - sizeof (UINTN))); + return PeiServices; +} + +VOID SetPeiServicesTablePointer ( + IN CONST EFI_PEI_SERVICES ** PeiServicesTablePointer +){ + DESCRIPTOR_TABLE Idtr; + + CPULib_SaveIdt (&Idtr); + (*(UINTN*)(Idtr.Base - sizeof (UINTN))) = (UINTN)PeiServicesTablePointer; +} +#else +EFI_PEI_SERVICES ** GetPeiServicesTablePointer (VOID){ +_asm { + push eax + push eax + movq [esp], mm7 + pop eax + pop edx + emms + } +} +#endif + +EFI_STATUS PciCfgModify( + IN CONST EFI_PEI_SERVICES ** PeiServices, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN SetBits, + IN UINTN ClearBits +){ + if ((*PeiServices)->PciCfg==NULL) return EFI_NOT_AVAILABLE_YET; + return (*PeiServices)->PciCfg->Modify( + (EFI_PEI_SERVICES**)PeiServices, (*PeiServices)->PciCfg, + Width, Address, +#if PI_SPECIFICATION_VERSION < 0x00010000 + SetBits, ClearBits +#else + &SetBits, &ClearBits +#endif + ); +} +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Library/Print.c b/Library/Print.c new file mode 100644 index 0000000..88e6806 --- /dev/null +++ b/Library/Print.c @@ -0,0 +1,414 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//************************************************************************* +// $Header: /Alaska/SOURCE/Core/Library/Print.c 7 7/10/09 4:01p Felixp $ +// +// $Revision: 7 $ +// +// $Date: 7/10/09 4:01p $ +//************************************************************************* +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/Library/Print.c $ +// +// 7 7/10/09 4:01p Felixp +// Function headers added +// +// 6 5/19/06 10:28p Felixp +// Updated to use NEXT_NODE & NODE_LENGTH macros +// +// 5 3/13/06 1:52a Felixp +// +// 4 10/12/05 8:28p Ambikas +// DevicePathToStr: Buffer length increased from 256 to 512. +// +// 3 7/18/05 3:18p Felixp +// +// 2 5/31/05 11:03a Andriyn +// +// 1 1/04/05 6:22p Markw +// +// +//************************************************************************* +// +// +// Name: Print.c +// +// Description: +// Contains functions which convert device paths to strings. +// +// +//************************************************************************* + +#include +#include + +CHAR8 DefaultDevicePath[]="DevicePath(Type %i, SubType %i)"; + +CHAR8 *HWDP[] = { + "PCI(%X|%X)\\", //HW_PCI_DP + "Pccard(Socket %i)\\", //HW_PCCARD_DP + "VenHw(%g)\\" //HW_VENDOR_DP +}; + +CHAR8 *ACPIDP[] = { + "Acpi(%x, %x)\\" //ACPI_DP +}; + +CHAR8 *MSGDP[] = { + "ATA(%s, %i)\\", //MSG_ATAPI_DP + "SCSI(%i, %i)\\", //MSG_SCSI_DP + "VenMsg(%g)\\" //MSG_VENDOR_DP +}; + +CHAR8 *MEDIADP[] = { + "HD(Part%i, Sig %s)\\", //MEDIA_HARDDRIVE_DP + "CDROM(Entry%i)\\", //MEDIA_CDROM_DP + "VenMedia(%g)\\", //MEDIA_VENDOR_DP + "%g\\" //MEDIA_FILEPATH_DP +}; + +//************************************************************************* +// +// +// Name: HWToStr +// +// Description: +// UINTN HWToStr(IN EFI_DEVICE_PATH_PROTOCOL *Path, OUT CHAR8 *Str) converts +// the provided hardware device path to a string. +// +// Input: +// IN EFI_DEVICE_PATH_PROTOCOL *Path +// The hardware device path which is desired as a string. +// +// OUT CHAR8 *Str +// ASCII string form of device path. +// +// Output: +// UINTN number of characters in Str, not including the null-terminator. +// +// Modified: +// +// Referrals: +// Sprintf +// +// Notes: +// Helper function for DevicePathToStr. +// +// +//************************************************************************* +UINTN HWToStr( + EFI_DEVICE_PATH_PROTOCOL *Path, + CHAR8 *Str + ) +{ + switch(Path->SubType) + { + case HW_PCI_DP: + return Sprintf(Str,HWDP[0],((PCI_DEVICE_PATH*)Path)->Device,((PCI_DEVICE_PATH*)Path)->Function); + case HW_PCCARD_DP: + return Sprintf(Str,HWDP[1],((PCCARD_DEVICE_PATH*)Path)->Function); + case HW_VENDOR_DP: + return Sprintf(Str,HWDP[2],&((VENDOR_DEVICE_PATH*)Path)->Guid); + } + + return Sprintf(Str,DefaultDevicePath,Path->Type,Path->SubType); +} + +//************************************************************************* +// +// +// Name: ACPIToStr +// +// Description: +// UINTN ACPIToStr(IN EFI_DEVICE_PATH_PROTOCOL *Path, OUT CHAR8 *Str) +// converts the provided ACPI device path to a string. +// +// Input: +// IN EFI_DEVICE_PATH_PROTOCOL *Path +// The ACPI device path which is desired as a string. +// +// OUT CHAR8 *Str +// ASCII string form of device path. +// +// Output: +// UINTN number of characters in Str, not including the null-terminator. +// +// Modified: +// +// Referrals: +// Sprintf +// +// Notes: +// Helper function for DevicePathToStr. +// +// +//************************************************************************* +UINTN ACPIToStr( + EFI_DEVICE_PATH_PROTOCOL *Path, + CHAR8 *Str + ) +{ + switch(Path->SubType) + { + case ACPI_DP: + return Sprintf(Str,ACPIDP[0], ((ACPI_HID_DEVICE_PATH*)Path)->HID, ((ACPI_HID_DEVICE_PATH*)Path)->UID); + } + return Sprintf(Str,DefaultDevicePath,Path->Type,Path->SubType); +} + +//************************************************************************* +// +// +// Name: MSGToStr +// +// Description: +// UINTN MSGToStr(IN EFI_DEVICE_PATH_PROTOCOL *Path, OUT CHAR8 *Str) +// converts the message device path to a string. +// +// Input: +// IN EFI_DEVICE_PATH_PROTOCOL *Path +// The message device path which is desired as a string. +// +// OUT CHAR8 *Str +// ASCII string form of device path. +// +// Output: +// UINTN number of characters in Str, not including the null-terminator. +// +// Modified: +// +// Referrals: +// Sprintf +// +// Notes: +// Helper function for DevicePathToStr. +// +// +//************************************************************************* +UINTN MSGToStr( + EFI_DEVICE_PATH_PROTOCOL *Path, + CHAR8 *Str + ) +{ + switch(Path->SubType) + { + case MSG_ATAPI_DP: + if (((ATAPI_DEVICE_PATH*)Path)->PrimarySecondary == 0) + return Sprintf(Str,MSGDP[0], "Master",((ATAPI_DEVICE_PATH*)Path)->Lun); + else if (((ATAPI_DEVICE_PATH*)Path)->PrimarySecondary == 1) + return Sprintf(Str,MSGDP[0], L"Slave", ((ATAPI_DEVICE_PATH*)Path)->Lun); + else break; + case MSG_SCSI_DP: + return Sprintf(Str,MSGDP[1], ((SCSI_DEVICE_PATH*)Path)->Pun, ((SCSI_DEVICE_PATH*)Path)->Lun); + case MSG_VENDOR_DP: + return Sprintf(Str,MSGDP[2], ((VENDOR_DEVICE_PATH*)Path)->Guid); + case MSG_USB_DP: + return Sprintf(Str,"USB(%x,%x)\\", + ((USB_DEVICE_PATH*)Path)->ParentPortNumber,((USB_DEVICE_PATH*)Path)->InterfaceNumber); + + } + return Sprintf(Str,DefaultDevicePath,Path->Type,Path->SubType); +} + +//************************************************************************* +// +// +// Name: MEDIAToStr +// +// Description: +// UINTN MEDIAToStr(IN EFI_DEVICE_PATH_PROTOCOL *Path, OUT CHAR8 *Str) +// converts the media device path to a string. +// +// Input: +// IN EFI_DEVICE_PATH_PROTOCOL *Path +// The media device path which is desired as a string. +// +// OUT CHAR8 *Str +// ASCII string form of device path. +// +// Output: +// UINTN number of characters in Str, not including the null-terminator. +// +// Modified: +// +// Referrals: +// Sprintf +// +// Notes: +// Helper function for DevicePathToStr. +// +// +//************************************************************************* +UINTN MEDIAToStr( + EFI_DEVICE_PATH_PROTOCOL *Path, + CHAR8 *Str + ) +{ + switch(Path->SubType) + { + case MEDIA_HARDDRIVE_DP: + // TODO: Find out hard drive signature format to display. + return Sprintf(Str,MEDIADP[0], ((HARDDRIVE_DEVICE_PATH*)Path)->PartitionNumber, "?");// ((HARDDRIVE_DEVICE_PATH*)Path)->Signature); + case MEDIA_CDROM_DP: + return Sprintf(Str,MEDIADP[1], ((CDROM_DEVICE_PATH*)Path)->BootEntry); + case MEDIA_VENDOR_DP: + return Sprintf(Str,MEDIADP[2], ((VENDOR_DEVICE_PATH*)Path)->Guid); + case MEDIA_FILEPATH_DP: + return Sprintf(Str,MEDIADP[3], &((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH*)Path)->NameGuid); + } + return Sprintf(Str,DefaultDevicePath,Path->Type,Path->SubType); +} + +//************************************************************************* +// +// +// Name: UnknownToStr +// +// Description: +// UINTN UnknownToStr(IN EFI_DEVICE_PATH_PROTOCOL *Path, OUT CHAR8 *Str) +// converts the device path to a default generic string. +// +// Input: +// IN EFI_DEVICE_PATH_PROTOCOL *Path +// The device path which is desired as a string. +// +// OUT CHAR8 *Str +// ASCII string form of device path. +// +// Output: +// UINTN number of characters in Str, not including the null-terminator. +// +// Modified: +// +// Referrals: +// Sprintf +// +// Notes: +// Helper function for DevicePathToStr. +// +// +//************************************************************************* +UINTN UnknownToStr( + EFI_DEVICE_PATH_PROTOCOL *Path, + CHAR8 *Str + ) +{ + return Sprintf(Str,DefaultDevicePath,Path->Type,Path->SubType); +} + +//************************************************************************* +// +// +// Name: DevicePathToStr +// +// Description: +// EFI_STATUS DevicePathToStr(IN EFI_DEVICE_PATH_PROTOCOL *Path, +// OUT CHAR8 **Str) convert the provided device path into string. Str is +// allocated by this routine. It must be freed by the caller. +// +// Input: +// IN EFI_DEVICE_PATH_PROTOCOL *Path +// The device path which is desired as a string. +// +// OUT CHAR8 **Str +// Address to store the pointer for the device path's string. User is +// responsible for freeing this memory. +// +// Output: +// EFI_UNSUPPORTED, if string conversion fails. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// NEXT_NODE +// MallocZ +// MemCpy +// +// Notes: +// This function is intended for debug purpose only. +// It does not provide support for all variety of device path types. +// +// +//************************************************************************* +EFI_STATUS DevicePathToStr( + EFI_DEVICE_PATH_PROTOCOL *Path, + CHAR8 **Str + ) +{ + CHAR8 Buffer[512]; + CHAR8 *p = Buffer; + UINTN Count = 0; + UINTN Length; + + for(;;) + { + switch(Path->Type) + { + case HARDWARE_DEVICE_PATH: + Count = HWToStr(Path, p); + break; + case ACPI_DEVICE_PATH: + Count = ACPIToStr(Path, p); + break; + case MESSAGING_DEVICE_PATH: + Count = MSGToStr(Path, p); + break; + case MEDIA_DEVICE_PATH: + Count = MEDIAToStr(Path, p); + break; + case END_DEVICE_PATH: + Count = 0; + break; + case END_DEVICE_PATH1: + *p = '|'; + *(p+1) = '\0'; + Count = 1; + break; + default: + Count = UnknownToStr(Path, p); + } + + p += Count; + + if (Count == -1) return EFI_UNSUPPORTED; + if (isEndNode(Path) && Path->SubType == END_ENTIRE_SUBTYPE) break; + + Path = NEXT_NODE(Path); + } + + Length = (p - Buffer) * sizeof(CHAR8); + + *Str = (CHAR8*)MallocZ(Length+1); + + MemCpy(*Str, Buffer, Length); + + return EFI_SUCCESS; +} + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Library/SmmAmiBufferValidationLib.c b/Library/SmmAmiBufferValidationLib.c new file mode 100644 index 0000000..acc9a3d --- /dev/null +++ b/Library/SmmAmiBufferValidationLib.c @@ -0,0 +1,239 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2014, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/AmiBufferValidationLib/SmmAmiBufferValidationLib.c 4 1/06/15 10:21a Aaronp $ +// +// $Revision: 4 $ +// +// $Date: 1/06/15 10:21a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/AmiBufferValidationLib/SmmAmiBufferValidationLib.c $ +// +// 4 1/06/15 10:21a Aaronp +// [TAG] EIP198890 +// [Category] Improvement +// [Description] Use of CORE_COMBINED_VERSION requires Token.h to be +// included. +// +// 3 12/30/14 4:08p Aaronp +// [TAG] EIP198005 +// [Category] Improvement +// [Description] Added support for pre PI 1.2 +// +// 2 11/26/14 10:33a Aaronp +// Updated function headers with additional information that was added to +// the AptioV component. +// +// 1 11/07/14 12:07p Aaronp +// Initial addition of AmiBufferValidationLib +// +//********************************************************************** + +//********************************************************************** +// +// +// Name: SmmAmiBufferValidationLib.c +// +// Description: Source file that defines the AmiBufferValidationLib functions +// used for validating that buffer addresses and MMIO addreses +// do not reside in SMM. The file also provides a function to +// validate that a buffer does reside in SMM. +// +// +//********************************************************************** +#include +#include +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A) +#include +#else +#include +#endif + +/// Internal list of SMRAM regions +EFI_SMRAM_DESCRIPTOR *SmmAmiBufferValidationLibSmramRanges = NULL; + +/// Number of SMRAM regions in the internal list +UINTN SmmAmiBufferValidationLibNumberOfSmramRange = 0; + +// +//---------------------------------------------------------------------------- +// Procedure: AmiValidateMemoryBuffer +// +// Description: Function verifies the buffer to make sure its address range is legal for a memory buffer. A legal memory +// buffer is one that lies entirely outside of SMRAM. SMI handlers that receive buffer address and/or size +// from outside of SMM at runtime must validate the buffer using this function prior to using it or passing +// to other SMM interfaces. +// +// Input: +// VOID *Buffer - Buffer address +// UINTN BufferSize - Size of the Buffer +// +// Output: +// EFI_SUCCESS - The buffer address range is valid and can be safely used. +// EFI_ACCESS_DENIED - The buffer can't be used because its address range overlaps with protected area such as SMRAM. +// EFI_INVALID_PARAMETER - The buffer can't be used because its address range is invalid. +// EFI_NOT_FOUND - The buffer can't be used because its validity cannot be verified. Normally due to the SMRAM ranges were not available. +//---------------------------------------------------------------------------- +// +EFI_STATUS AmiValidateMemoryBuffer(VOID* Buffer, UINTN BufferSize){ + UINTN i; + UINTN BufferAddress; + + if (SmmAmiBufferValidationLibNumberOfSmramRange==0) return EFI_NOT_FOUND; + + BufferAddress = (UINTN)Buffer; + if (BufferAddress + BufferSize < BufferAddress) return EFI_INVALID_PARAMETER; // overflow + for (i = 0; i < SmmAmiBufferValidationLibNumberOfSmramRange; i ++) { + if ( BufferAddress >= SmmAmiBufferValidationLibSmramRanges[i].CpuStart + && BufferAddress < SmmAmiBufferValidationLibSmramRanges[i].CpuStart + SmmAmiBufferValidationLibSmramRanges[i].PhysicalSize + ) return EFI_ACCESS_DENIED; // Buffer starts in SMRAM + if ( BufferAddress < SmmAmiBufferValidationLibSmramRanges[i].CpuStart + && BufferAddress+BufferSize > SmmAmiBufferValidationLibSmramRanges[i].CpuStart + ) return EFI_ACCESS_DENIED; // Buffer overlaps with SMRAM + } + + return EFI_SUCCESS; +} + +// +//---------------------------------------------------------------------------- +// Procedure: AmiValidateMmioBuffer +// +// Description: Function verifies the buffer to make sure its address range is legal for a MMIO buffer. A legal MMIO buffer is one that lies +// entirely outside of SMRAM. SMI handlers that receive a buffer address and/or size from outside of SMM at runtime must validate +// the buffer using this function prior to using the MMIO Buffer or passing to other SMM interfaces. +// +// Input: +// VOID *Buffer - Buffer address +// UINTN BufferSize - Size of the Buffer +// +// Output: +// EFI_SUCCESS - The buffer address range is valid and can be safely used. +// EFI_ACCESS_DENIED - The buffer can't be used because its address range overlaps with protected area such as SMRAM. +// EFI_INVALID_PARAMETER - The buffer can't be used because its address range is invalid. +// EFI_NOT_FOUND - The buffer can't be used because its validity cannot be verified. Normally due to the SMRAM ranges were not available. +//---------------------------------------------------------------------------- +// +EFI_STATUS AmiValidateMmioBuffer(VOID* Buffer, UINTN BufferSize){ + return AmiValidateMemoryBuffer(Buffer,BufferSize); +} + +// +//---------------------------------------------------------------------------- +// Procedure: AmiValidateSmramBuffer +// +// Description: Function verifies the buffer to make sure it wholly resides in the SMRAM. +// +// Input: +// IN VOID *Buffer - Buffer address +// IN UINTN BufferSize - Size of the Buffer +// +// Output: +// EFI_SUCCESS - The buffer resides in the SMRAM and can be safely used. +// EFI_ACCESS_DENIED - The buffer can't be used because at least one byte of the buffer is outside of SMRAM. +// EFI_INVALID_PARAMETER - The buffer can't be used because its address range is invalid. +// EFI_NOT_FOUND - The buffer can't be used because its validity cannot be verified. Normally due to the SMRAM ranges were not available. +//---------------------------------------------------------------------------- +// +EFI_STATUS AmiValidateSmramBuffer(VOID* Buffer, UINTN BufferSize){ + UINTN i; + UINTN BufferAddress; + + if (SmmAmiBufferValidationLibNumberOfSmramRange==0) return EFI_NOT_FOUND; + + BufferAddress = (UINTN)Buffer; + if (BufferAddress + BufferSize < BufferAddress) return EFI_INVALID_PARAMETER; // overflow + for (i = 0; i < SmmAmiBufferValidationLibNumberOfSmramRange; i ++) { + if ( BufferAddress >= SmmAmiBufferValidationLibSmramRanges[i].CpuStart + && BufferAddress+BufferSize <= SmmAmiBufferValidationLibSmramRanges[i].CpuStart + SmmAmiBufferValidationLibSmramRanges[i].PhysicalSize + ) return EFI_SUCCESS; // Entire Buffer is in SMRAM + } + + return EFI_ACCESS_DENIED; +} + +// +//---------------------------------------------------------------------------- +// Procedure: InitAmiBufferValidationLib +// +// Description: Performs the necessary initialization so that the buffer validation functions will operate +// correctly when they are called. +// +// Input: +// IN EFI_HANDLE ImageHandle - The handle of this image +// IN EFI_SYSTEM_TABLE *SystemTable - Pointer to the EFI_SYSTEM_TABLE +// +// Output: +// EFI_NOT_FOUND - The Smm Access protocol could not be found +// EFI_OUT_OF_RESOURCES - An allocation failed because it could not find any memory resources +// EFI_INVALID_PARAMETER - An invalid parameter was passed to one of the functions +// EFI_SUCCESS - The necessary functions were initialized +//---------------------------------------------------------------------------- +// +EFI_STATUS EFIAPI InitAmiBufferValidationLib(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable){ + EFI_STATUS Status; +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A) + EFI_SMM_ACCESS2_PROTOCOL *SmmAccess; +#else + EFI_SMM_ACCESS_PROTOCOL *SmmAccess; +#endif + UINTN Size; + +#if defined(CORE_COMBINED_VERSION)&&(CORE_COMBINED_VERSION>0x4028a) + InitAmiSmmLib(ImageHandle,SystemTable); +#endif + + // Get SMRAM information +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A) + Status = pBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess); +#else + Status = pBS->LocateProtocol (&gEfiSmmAccessProtocolGuid, NULL, (VOID **)&SmmAccess); +#endif + if (EFI_ERROR(Status)) return Status; + + Size = 0; + Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL); + if (Status != EFI_BUFFER_TOO_SMALL) return Status; + Status = pSmst->SmmAllocatePool (EfiRuntimeServicesData, Size, (VOID **)&SmmAmiBufferValidationLibSmramRanges); + if (EFI_ERROR(Status)){ + SmmAmiBufferValidationLibSmramRanges = NULL; + return Status; + } + Status = SmmAccess->GetCapabilities (SmmAccess, &Size, SmmAmiBufferValidationLibSmramRanges); + if (EFI_ERROR(Status)){ + pSmst->SmmFreePool (SmmAmiBufferValidationLibSmramRanges); + SmmAmiBufferValidationLibSmramRanges = NULL; + return Status; + } + SmmAmiBufferValidationLibNumberOfSmramRange = Size / sizeof (EFI_SMRAM_DESCRIPTOR); + + return EFI_SUCCESS; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2014, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Library/StdLibC.c b/Library/StdLibC.c new file mode 100644 index 0000000..749c5cc --- /dev/null +++ b/Library/StdLibC.c @@ -0,0 +1,1831 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/Library/StdLibC.c 22 8/15/12 5:41p Artems $ +// +// $Revision: 22 $ +// +// $Date: 8/15/12 5:41p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/Library/StdLibC.c $ +// +// 22 8/15/12 5:41p Artems +// [TAG] EIP N/A +// [Category] Spec Update +// [Severity] Minor +// [Description] Added correct error codes for display purposes +// [Files] StdLib.c +// +// 21 11/17/11 6:12p Artems +// Fixed bug: PI errors don't display properly +// +// 20 11/11/11 3:37p Artems +// Added UEFI 2.3.1 error codes +// +// 19 2/05/11 3:11p Artems +// Added PI 1.0-1.1 error and warning messages +// +// 18 8/07/09 4:45p Felixp +// Minor bug fix in StrtolEx function. +// The code of Sprintf_s_va_list and Swprintf_s_va_list functions is +// optimized. +// +// 17 7/31/09 4:24p Felixp +// Minor improvements in Sprintf_s_va_list and Swprintf_s_va_list +// functions. +// +// 16 7/30/09 4:23p Vyacheslava +// Minor bug fix. EIP#24453: Synopsis: CPU exception when printing long +// debug messages. +// +// 15 7/29/09 4:04p Vyacheslava +// Buffer overflow protection has been added for Sprintf. +// +// 14 7/28/09 4:52p Vyacheslava +// Bug fix. EIP#24453: Synopsis: CPU exception when printing long +// debug messages. +// +// 13 7/10/09 4:35p Felixp +// +// 12 7/10/09 3:49p Felixp +// Function headers added +// +// 11 5/04/09 3:21p Felixp +// Bug fix in Strcpy and Wcscpy functions. +// The functions were returning pointer to the next character after the +// terminator of the destination string. +// The code is updated to return pointer to the beginning of the +// destination string. +// +// 10 8/24/06 9:26a Felixp +// Preliminary x64 support (work in progress): +// 1. Processor architecture specific functions moved to a processor +// library +// 2. Makefile removed (AmiLib files are build by the AmiPeiLib and +// AmeDxeLib makefile) +// 3. Tokens.c added +// +// 9 5/19/06 10:25p Felixp +// Strcpy, Wcscpy changed to return pointer to the end of the string +// +// 8 4/30/06 9:40p Felixp +// +// 7 7/11/05 4:52p Felixp +// Sprintf and Swprinf: added support for %c (character printing) +// +// 6 4/22/05 4:47p Felixp +// +// 5 4/21/05 8:01p Felixp +// Spintf and Swprinf changed to reflect value changes for AMI Status Code +// (see the corresponding change in EFI.h +// +// 4 4/02/05 2:25p Felixp +// Swprintf function added +// +// 3 3/25/05 5:25p Felixp +// Strtol modified to support both ASCII and Unicode strings +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 12/23/04 9:41a Felixp +// +// 14 12/15/04 9:06p Felixp +// LegacyBoot application added +// Minor build process improvements +// +// 13 12/15/04 3:52p Markw +// Added Strstr. +// +// 12 11/24/04 9:36a Felixp +// int64 suppot added to Itoa and Itow +// +// 11 11/10/04 5:14p Felixp +// 1. Bug fixes in Itoa and Itow +// 2. const qualifiers removed +// +// 10 10/22/04 7:42p Felixp +// +// 9 9/21/04 10:47a Robert +// Sprintf_va_list needed to add a carrage return character when it found +// a new line character +// +// 8 4/04/04 2:58p Felixp +// +// 7 3/30/04 3:42p Markw +// Added sprintf status code support. +// +// 6 3/30/04 9:51a Markw +// Added Sprintf declaration before Sprintf_va_list. +// +// 5 3/29/04 5:26p Markw +// Added Guid printing through sprintf, and renamed some functions. Split +// sprintf into the variable parameter list and non-varialble parameter +// list. +// +// 4 3/26/04 5:59p Markw +// Replaced a broken printf with a working sprintf. Does not support of +// floating points. +// +// 3 3/17/04 12:01p Markw +// Changed unsigned (where it should be size_t) to UINTN. +// +// 2 2/26/04 3:23p Felixp +// +// 1 1/22/04 3:04p Markw +// +//************************************************************************* +// +// +// Name: StdLibC.c +// +// Description: +// StdLibC.c contains a number of standard C library functions, including +// but not limited to string and cctype library functions. +// +// +//************************************************************************* +#include + +char EfiErrorStatus[][25] = +{ + "EFI_LOAD_ERROR", + "EFI_INVALID_PARAMETER", + "EFI_UNSUPPORTED", + "EFI_BAD_BUFFER_SIZE", + "EFI_BUFFER_TOO_SMALL", + "EFI_NOT_READY", + "EFI_DEVICE_ERROR", + "EFI_WRITE_PROTECTED", + "EFI_OUT_OF_RESOURCES", + "EFI_VOLUME_CORRUPTED", + "EFI_VOLUME_FULL", + "EFI_NO_MEDIA", + "EFI_MEDIA_CHANGED", + "EFI_NOT_FOUND", + "EFI_ACCESS_DENIED", + "EFI_NO_RESPONSE", + "EFI_NO_MAPPING", + "EFI_TIMEOUT", + "EFI_NOT_STARTED", + "EFI_ALREADY_STARTED", + "EFI_ABORTED", + "EFI_ICMP_ERROR", + "EFI_TFTP_ERROR", + "EFI_PROTOCOL_ERROR", + "EFI_INCOMPATIBLE_VERSION", + "EFI_SECURITY_VIOLATION", + "EFI_CRC_ERROR" +#if EFI_SPECIFICATION_VERSION<0x20000 + ,"EFI_NOT_AVAILABLE_YET", + "EFI_UNLOAD_IMAGE" +#else + ,"EFI_END_OF_MEDIA", + "EFI_UNDEFINED_29", + "EFI_UNDEFINED_30", + "EFI_END_OF_FILE", + "EFI_INVALID_LANGUAGE", + "EFI_COMPROMISED_DATA" +#endif +}; + +char PiErrorStatus[][25] = +{ + "EFI_INTERRUPT_PENDING", + "EFI_REQUEST_UNLOAD_IMAGE", + "EFI_NOT_AVAILABLE_YET" +}; + +char AmiErrorStatus[][25] = +{ + "EFI_DBE_EOF", + "EFI_DBE_BOF" +}; + +char EfiWarningStatus[][26] = +{ + "EFI_WARN_UNKNOWN_GLYPH", + "EFI_WARN_DELETE_FAILURE", + "EFI_WARN_WRITE_FAILURE", + "EFI_WARN_BUFFER_TOO_SMALL" +}; + +char PiWarningStatus[][35] = +{ + "EFI_WARN_INTERRUPT_SOURCE_PENDING", + "EFI_WARN_INTERRUPT_SOURCE_QUIESCED" +}; + +#if EFI_SPECIFICATION_VERSION<0x20000 +#define NUM_OF_EFI_ERRORS 29 +#else +#define NUM_OF_EFI_ERRORS 30 +#endif +#define NUM_OF_EFI_WARNINGS 4 +#define NUM_OF_AMI_ERRORS 2 +#define NUM_OF_PI_ERRORS 3 +#define NUM_OF_PI_WARNINGS 2 + +char EfiUnknown[] = "Status Code"; //If unknown value. + +CHAR16 * wcsupr(CHAR16 *str); + +#define true TRUE +#define false FALSE + +//************************************************************************* +// +// +// Name: Stdlib_Functions +// +// Description: +// C standard general utilities library functions, typically found in +// stdlib.h, that are defined in the AMI library. +// +// Fields: Header Function Description +// ------------------------------------------------------------------ +// AmiLib Atoi Convert 8-bit ASCII string to INT32. +// AmiLib StrtolEx Convert 8-bit ASCII string to INT64. +// AmiLib ItoaEx Convert INT64 to 8-bit ASCII string. +// AmiLib ItowEx Convert INT64 to 16-bit Unicode string. +// AmiDxeLib Malloc Allocate memory from EfiBootServicesData. +// AmiDxeLib MallocZ Allocate memory from EfiBootServicesData that has been cleared with zeros. +// +// Notes: +// Header details which header file contains the function prototype for +// the above functions; append .h to the given name. None indicates that +// no header file contains a function prototype. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: Ctype_Functions +// +// Description: +// C character handling functions, typically found in ctype.h, that are +// defined in the AMI library. +// +// Fields: Header Function Description +// ------------------------------------------------------------------ +// None Toupper Convert lowercase 8-bit ASCII character to uppercase. +// +// Notes: +// Header details which header file contains the function prototype for +// the above functions; append .h to the given name. None indicates that +// no header file contains a function prototype. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: String_Functions +// +// Description: +// String related functions that are defined in the AMI library. +// +// Fields: Header Function Description +// ------------------------------------------------------------------ +// AmiLib Strlen Find length of null-terminated 8-bit ASCII string. +// AmiLib Wcslen Find length of null-terminated 16-bit Unicode string. +// AmiLib Strcpy Copy an 8-bit ASCII string into another string. +// AmiLib Wcscpy Copy a 16-bit Unicode string into another string. +// AmiLib Strcmp Compare two 8-bit ASCII strings to each other. +// AmiLib Wcscmp Compare two 16-bit Unicode strings to each other. +// AmiLib Strupr Convert an 8-bit ASCII string into all uppercase characters. +// AmiLib Wcsupr Convert a 16-bit Unicode string to all uppercase characters. +// AmiLib Strstr Find an occurrence of an 8-bit ASCII string inside another string. +// AmiLib Sprintf Print a formatted 8-bit ASCII string to a buffer. +// AmiLib Swprintf Print a formatted 16-bit Unicode string to a buffer. +// AmiLib Sprintf_s Print a formatted 8-bit ASCII string to a buffer of predetermined size. +// AmiLib Swprintf_s Print a formatted 16-bit Unicode string to a buffer of predetermined size. +// AmiLib ItoaEx Convert INT64 to 8-bit ASCII string. +// AmiLib ItowEx Convert INT64 to 16-bit Unicode string. +// +// Notes: +// Header details which header file contains the function prototype for +// the above functions; append .h to the given name. None indicates that +// no header file contains a function prototype. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: Cstring_Functions +// +// Description: +// C string handling functions, typically found in string.h, that are +// defined in the AMI library. +// +// Fields: Header Function Description +// ------------------------------------------------------------------ +// AmiLib Strlen Find length of null-terminated 8-bit ASCII string. +// AmiLib Wcslen Find length of null-terminated 16-bit Unicode string. +// AmiLib Strcpy Copy an 8-bit ASCII string into another string. +// AmiLib Wcscpy Copy a 16-bit Unicode string into another string. +// AmiLIb MemCpy Copy a buffer into another buffer. +// AmiLib Strcmp Compare two 8-bit ASCII strings to each other. +// AmiLib Wcscmp Compare two 16-bit Unicode strings to each other. +// AmiLib MemCmp Compare two buffers for equality. +// AmiLib Strupr Convert an 8-bit ASCII string into all uppercase characters. +// AmiLib Wcsupr Convert a 16-bit Unicode string to all uppercase characters. +// AmiLib Strstr Find an occurrence of an 8-bit ASCII string inside another string. +// AmiLib MemSet Fills a buffer with a user provided value. +// +// Notes: +// Header details which header file contains the function prototype for +// the above functions; append .h to the given name. None indicates that +// no header file contains a function prototype. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: Stdio_Functions +// +// Description: +// C standard I/O functions, typically found in stdio.h, that are +// defined in the AMI library. +// +// Fields: Header Function Description +// ------------------------------------------------------------------ +// AmiLib Sprintf Print a formatted 8-bit ASCII string to a buffer. +// AmiLib Swprintf Print a formatted 16-bit Unicode string to a buffer. +// AmiLib Sprintf_s Print a formatted 8-bit ASCII string to a buffer of predetermined size. +// AmiLib Swprintf_s Print a formatted 16-bit Unicode string to a buffer of predetermined size. +// +// Notes: +// Header details which header file contains the function prototype for +// the above functions; append .h to the given name. None indicates that +// no header file contains a function prototype. +// +// +//************************************************************************* + +//************************************************************************* +// +// +// Name: Toupper +// +// Description: +// INT32 Toupper(IN INT32 c) converts a lowercase ASCII character, c, to an +// uppercase ASCII character and returns its uppercase ASCII value. If c is +// not a valid lowercase ASCII character, returns c. +// +// Input: +// IN INT32 c +// ASCII value to be converted from lowercase to uppercase. +// +// Output: +// INT32 value of c, if c is not a valid lowercase ASCII character. +// Otherwise, INT32 ASCII value of c as an uppercase letter. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +int Toupper(int c) { + return (c>='a' && c<='z') ? c-'a'+'A' : c; +} + +//************************************************************************* +// +// +// Name: Strlen +// +// Description: +// UINTN Strlen(IN CHAR8 *string) takes a null-terminated CHAR8 string and +// returns its UINTN length (not including the null-terminator). +// +// Input: +// IN CHAR8 *string +// Pointer to a null-terminated CHAR8 string. +// +// Output: +// UINTN length of the string (not including the null-terminator). +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +UINTN Strlen(char *string) { + UINTN length=0; + while(*string++) length++; + return length; +} + +//************************************************************************* +// +// +// Name: Wcslen +// +// Description: +// UINTN Wcslen(IN CHAR16 *string) takes a null-terminated CHAR16 string and +// returns its UINTN length (not including the null-terminator). +// +// Input: +// IN CHAR16 *string +// Pointer to a null-terminated CHAR16 string. +// +// Output: +// UINTN length of the string (not including the null-terminator). +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +UINTN Wcslen(CHAR16 *string) { + UINTN length=0; + while(*string++) length++; + return length; +} + +//************************************************************************* +// +// +// Name: Strcpy +// +// Description: +// CHAR8* Strcpy(IN OUT CHAR8 *string1, IN CHAR8 *string2) copies the +// contents of a CHAR8 string, string2, into another CHAR8 string, string1. +// +// Input: +// IN OUT CHAR8 *string1 +// Pointer to a CHAR8 string buffer to receive the contents of string2. +// String size must be greater than or equal to string2. User is +// responsible for allocating the necessary memory resources. +// +// IN CHAR8 *string2 +// Pointer to a null-terminated CHAR8 string to be copied. +// +// Output: +// CHAR8* string pointer to the last character added to string1. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +char* Strcpy(char *string1,char *string2){ + char *dest = string1; + while(*string1++=*string2++); + return dest; +} + +//************************************************************************* +// +// +// Name: Wcscpy +// +// Description: +// CHAR16* Wcscpy(IN OUT CHAR16 *string1, IN CHAR16 *string2) copies the +// contents of a CHAR16 string, string2, into another CHAR16 string, string1. +// +// Input: +// IN OUT CHAR16 *string1 +// Pointer to a CHAR16 string buffer to receive the contents of string2. +// String size must be greater than or equal to string2. User is +// responsible for allocating the necessary memory resources. +// +// IN CHAR16 *string2 +// Pointer to a null-terminated CHAR16 string to be copied. +// +// Output: +// CHAR16* string pointer to the last character added to string1. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +CHAR16* Wcscpy(CHAR16 *string1, CHAR16* string2){ + CHAR16 *dest = string1; + while(*string1++=*string2++); + return dest; +} + +//************************************************************************* +// +// +// Name: Strcmp +// +// Description: +// INT32 Strcmp(IN CHAR8 *string1, IN CHAR8 *string2) compares two CHAR8 +// strings, string1 and string2, and returns 0 if they are identical, +// non-zero if they are not identical. +// +// Input: +// IN CHAR8 *string1 +// Pointer to a CHAR8 null-terminated string. +// +// IN CHAR8 *string2 +// Pointer to a CHAR8 null-terminated string. +// +// Output: +// INT32 non-zero value if both string1 and string2 are not identical. +// Otherwise, returns 0 if both string1 and string 2 are identical. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +int Strcmp( char *string1, char *string2 ) { + while(*string1 && *string1==*string2) {*string1++;*string2++;} + return *string1 - *string2; +} + +//************************************************************************* +// +// +// Name: Wcscmp +// +// Description: +// INT32 Wcscmp(IN CHAR16 *string1, IN CHAR16 *string2) compares two CHAR16 +// strings, string1 and string2, and returns 0 if they are identical, +// non-zero if they are not identical. +// +// Input: +// IN CHAR16 *string1 +// Pointer to a CHAR16 null-terminated string. +// +// IN CHAR16 *string2 +// Pointer to a CHAR16 null-terminated string. +// +// Output: +// INT32 non-zero value if both string1 and string2 are not identical. +// Otherwise, returns 0 if both string1 and string 2 are identical. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +int Wcscmp( CHAR16 *string1, CHAR16 *string2 ) { + while(*string1 && *string1==*string2) {*string1++;*string2++;} + return *string1 - *string2; +} + +//************************************************************************* +// +// +// Name: Atoi +// +// Description: +// INT32 Atoi(IN CHAR8 *string) converts an ASCII string that represents an +// integer into an actual INT32 integer value and returns the result. +// +// Input: +// IN CHAR8 *string +// Pointer to a CHAR8 string that represents an integer number. +// +// Output: +// INT32 value that the string represented. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +int Atoi(char *string) { + int value=0; + while (*string>='0' && *string<='9') { + value *=10; + value += *string-'0'; + string++; + } + return value; +} + +//************************************************************************* +// +// Name: ItoaHelper +// +// Description: +// CHAR8* ItoaHelper(IN INT64 value, IN OUT CHAR8 *string, IN INT32 radix, +// IN BOOLEAN is_int64) is a helper function for ItoaEx and ItowEx which +// converts an INT64 value into a CHAR8 ASCII representation in reverse +// order. +// +// Input: +// IN INT64 value +// Value to be converted. +// +// IN OUT CHAR8 *string +// Pointer to a CHAR8 string buffer that will hold the result of the reverse +// conversion. User is responsible for allocating the necessary memory +// resources. +// +// IN INT32 radix +// Radix of the conversion. +// +// IN BOOLEAN is_int64 +// TRUE if value is a 64-bit integer; FALSE if it's 32-bit. +// +// Output: +// CHAR8* string pointer to the last character added to the input string, +// which now contains an ASCII string that is the reverse of what value +// represents. +// +// Modified: +// +// Referrals: +// Div64 +// +// Notes: +// +//************************************************************************* +char * ItoaHelper(INT64 value, char *string,int radix, BOOLEAN is_int64) { + UINTN digit; + UINT64 v = (value>=0) + ? (UINT64) value + : (radix==10) + ? (UINT64)-value + : (is_int64) + ? (UINT64)value + : (UINT32)value; + if (v) + while (v) { + v = Div64(v,radix,&digit); + if (digit<0xa) *string=(char)(digit+'0'); + else *string=(char)(digit-0xa+'a'); + string++; + } + else *string++='0'; + if (radix==10 && value<0) *string++='-'; + *string--=0; + return string; +} + +//************************************************************************* +// +// +// Name: ItoaEx +// +// Description: +// CHAR8* ItoaEx(IN INT64 value, IN OUT CHAR8 *string, IN INT32 radix, +// IN BOOLEAN is_int64) converts an INT64 value into a CHAR8 ASCII +// representation and returns a pointer to the ASCII string. +// +// Input: +// IN INT64 value +// Value that needs to be converted into an ASCII representation. +// +// IN OUT CHAR8 *string +// Pointer to a CHAR8 string buffer which will contain the result of the +// conversion. User is responsible for allocating the necessary memory +// resources. +// +// IN INT32 radix +// Radix of the conversion. For example, 10 for decimal, 16 for hexadecimal, +// etc. +// +// IN BOOLEAN is_int64 +// TRUE if value is a 64-bit integer; FALSE if it's 32-bit. +// +// Output: +// CHAR8* string pointer, string, that contains the ASCII representation of +// value in the user requested radix. +// +// Modified: +// +// Referrals: +// ItoaHelper +// +// Notes: +// +// +//************************************************************************* +char * ItoaEx(INT64 value, char *string,int radix, BOOLEAN is_int64) { + char *strp=string; + char *str2p=ItoaHelper(value,strp,radix,is_int64); + //reverse string + while(strp +// +// Name: ItowEx +// +// Description: +// CHAR16* ItowEx(IN INT64 value, IN OUT CHAR16 *string, IN INT32 radix, +// IN BOOLEAN is_int64) converts an INT64 value into a 16-bit Unicode +// representation and returns a CHAR16 pointer to the string. +// +// Input: +// IN INT64 value +// Value that needs to be converted into an ASCII representation. +// +// IN OUT CHAR16 *string +// Pointer to a CHAR8 string buffer which will contain the result of the +// conversion. +// +// IN INT32 radix +// Radix of the conversion. For example, 10 for decimal, 16 for hexadecimal, +// etc. +// +// IN BOOLEAN is_int64 +// TRUE if value is a 64-bit integer; FALSE if it's 32-bit. +// +// Output: +// CHAR16* string pointer, string, that contains the 16-bit Unicode +// representation of value in the user requested radix. +// +// Modified: +// +// Referrals: +// ItoaHelper +// +// Notes: +// +// +//************************************************************************* +CHAR16 * ItowEx(INT64 value, CHAR16 *string,int radix, BOOLEAN is_int64) { + char s[0x100]; + CHAR16 *str = string; + char *send=ItoaHelper(value,(char*)s,radix,is_int64); + //convert to unicode + while(send>=s) { + *str++ = *send--; + } + *str=0; + return string; +} + +//************************************************************************* +// +// +// Name: StrtolEx +// +// Description: +// INT64 StrtolEx(IN CHAR8 *nptr, OUT CHAR8 **endptr, IN INT32 base, +// IN INT32 increment) converts a CHAR8 string representation of a number +// into an INT64 representation. +// +// Input: +// IN CHAR8 *nptr +// CHAR8 string to be converted into an INT64. +// +// OUT CHAR8 **endptr +// CHAR8 string pointer to the final character read from nptr. +// +// IN INT32 base +// The base of the string being passed in. If 0, string will be parsed by +// defaults; preceding "0x" treated as hexadecimal, preceding "0" treated as +// octal, everything else treated as decimal. +// +// IN INT32 increment +// The number of characters in between each number digit. For example, +// "14131" would be 1; "1 4 1 3 1" would be 2. +// +// Output: +// INT64 representation of the number in the ASCII nptr string using the +// provided base and increment amount. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +long StrtolEx(char *nptr,char **endptr,int base, int increment) { + unsigned char overflow=false; + char sign=1; + char digit; + long value=0; + + while(*nptr == ' ' || *nptr == '\t') nptr+=increment; + if (*nptr == '\0') {*endptr=(char*)nptr;return 0;} + + if (*nptr == '-') {sign = -1;nptr+=increment;} + if (*nptr == '+') nptr+=increment; + + if (!base) { + base=10; + if (*nptr == '0') { + base=8; + nptr+=increment; + if ((*nptr&0xdf)=='X') { //Check for 'x' or 'X' + base=16; + nptr+=increment; + } + } + } + while(true) { + if (*nptr >= '0' && *nptr <='9') digit=*nptr-'0'; + else if ((*nptr&0xdf)>='A'&& (*nptr&0xdf)<='Z') digit = (*nptr&0xdf) - 'A' + 0xa; + else break; + if (digit >= base) break; + value = value * base + digit; + if (sign==1) { + if ((unsigned) value >= (unsigned) 0x80000000) overflow=true; + } else if ((unsigned) value > (unsigned) 0x80000000) overflow=true; + nptr+=increment; + } + *endptr=(char*)nptr; + if (overflow) { + value=0x7fffffff; + if (sign==-1) value++; + } + return value*sign; +} + +//************************************************************************* +// +// +// Name: Strupr +// +// Description: +// CHAR8* Strupr(IN CHAR8 *str) converts a CHAR8 string to all uppercase +// characters. +// +// Input: +// IN CHAR8 *str +// CHAR8 string to be converted to all uppercase. +// +// Output: +// CHAR8* string pointer to the start of the modified string. +// +// Modified: +// +// Referrals: +// +// Notes: +// Original string will be modified! +// +// +//************************************************************************* +char * Strupr(char *str) { + char *strptr=str; + while (*strptr) { //End of string? + if (*strptr >=0x61 && *strptr<=0x7a) *strptr-=0x20; //If char is lower case, convert to upper. + strptr++; //Next char + } + return str; +} + +//************************************************************************* +// +// +// Name: Wcsupr +// +// Description: +// CHAR16* Wcsupr(IN CHAR16 *str) converts a CHAR16 string to all uppercase +// characters. +// +// Input: +// IN CHAR16 *str +// CHAR16 string to be converted to all uppercase. +// +// Output: +// CHAR16* string pointer to the start of the modified string. +// +// Modified: +// +// Referrals: +// +// Notes: +// Original string will be modified! +// +// +//************************************************************************* +CHAR16 * Wcsupr(CHAR16 *str) { + CHAR16 *strptr=str; + while (*strptr) { //End of string? + if (*strptr >=0x61 && *strptr<=0x7a) *strptr-=0x20; //If char is lower case, convert to upper. + strptr++; //Next char + } + return str; +} + +//************************************************************************* +// +// +// Name: Strstr +// +// Description: +// CHAR8* Strstr(IN CONST CHAR8 *string, IN CONST CHAR8 *strSearch) locates +// strSearch within string, and returns a pointer to the start of the located +// string. +// +// Input: +// IN CONST CHAR8 *string +// The string to be searched through. +// +// IN CONST CHAR8 *strSearch +// The string to locate/find. +// +// Output: +// CHAR8* string pointer to the start of the located string if strSearch is +// located. If not found, returns a pointer to the end of the input string. +// If strSearch is an empty null-terminated string, returns the start of +// string. +// +// Modified: +// +// Referrals: +// +// Notes: +// +// +//************************************************************************* +char *Strstr( + const char *string, + const char *strSearch +) +{ + char *StartPos = (char *)string; + + if (!*strSearch) return StartPos; + + while (*StartPos) + { + char *p = StartPos; + char *q = (char *) strSearch; + + while (*q && *p == *q) {++p;++q;} + if (!*q) return StartPos; + ++StartPos; + } + return StartPos; +} + +//************************************************************************* +// +// Name: Sprintf_va_list +// +// Description: +// UINTN Sprintf_va_list(OUT CHAR8 *buffer, IN CHAR8 *format, +// IN va_list arg) produces a null-terminated ASCII string in the output +// buffer. The ASCII string is produced by parsing the format string +// specified by format. Arguments are pulled from the variable argument +// list, specified by arg, based on the contents of the format string. The +// number of ASCII characters in the produced output buffer is returned, not +// including the null-terminator. +// +// Input: +// buffer - Pointer to a null-terminated output ASCII string buffer. +// User is responsible for allocating the necessary memory resources! +// +// BufferSize - Size of the buffer in bytes. +// +// format - Pointer to a null-terminated format ASCII string. +// +// arg - Marker for the variable argument list. +// +// Output: +// UINTN - number of ASCII characters in the produced output buffer, not +// including the null-terminator. +// +// Referrals: +// va_arg +// Strtol +// Sprintf +// Strupr +// I64toa +// Itoa +// Strlen +// +// Notes: Refer to Sprintf function for format string syntax. +// +//************************************************************************* +UINTN Sprintf_va_list( char *buffer, char *format, va_list arg ) +{ + return Sprintf_s_va_list( buffer, 0, format, arg ); +} + +//************************************************************************* +// +// +// Name: Sprintf +// +// Description: +// UINTN Sprintf(OUT CHAR8 *Buffer, IN CHAR8 *Format, IN ...) produces a +// null-terminated ASCII string in the output Buffer. The ASCII string is +// produced by parsing the format string specified by Format. Arguments are +// pulled from the variable argument list based on the contents of the format +// string. The number of ASCII characters in the produced output buffer is +// returned, not including the null-terminator. See notes for format string +// information. +// +// Input: +// OUT CHAR8 *Buffer +// Pointer to a null-terminated output ASCII string buffer. User is +// responsible for allocating the necessary memory resources! +// +// IN CHAR8 *Format +// Pointer to a null-terminated format ASCII string. +// +// IN ... +// Variable argument list which provides the data/variables used within the +// format string. +// +// Output: +// UINTN number of ASCII characters in the produced output buffer, not +// including the null-terminator. +// +// Modified: +// +// Referrals: +// va_start +// Sprintf_va_list +// va_end +// +// Notes: +// Objects inside the format string have the following syntax. +// %[flags][width]type +// +// *** [flags] *** +// +// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . +// . Flag . Description +// . . +// . - . The field is left justified. If flag is not specified, then +// . . the field is right justified. +// . . +// . space . Prefix a space character to a number. Only valid for types X, +// . . x, and d. +// . . +// . + . Prefix a plus character to a number. Only valid for types X, +// . . x, and d. If both space and `+' are specified, then space is +// . . ignored. +// . . +// . 0 . Pad with `0' characters to the left of a number. Only valid +// . . for types X, x, and d. +// . . +// . L, l . The number being printed is a UINT64. Only valid for types X, +// . . x, and d. If this flag is not specified, then the number being +// . . printed is an int. +// . . +// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . +// +// NOTE +// All invalid [flags] are ignored. +// +// *** [width] *** +// +// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . +// . Width . Description +// . . +// . * . The width of the field is specified by a UINTN argument in the +// . . argument list. +// . . +// . Number . The number specified as a decimal value represents the width of +// . . the field. +// . . +// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . +// +// NOTE +// If [width] is not specified, then a field width of 0 is assumed. +// +// *** type *** +// +// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . +// . Type . Description +// . . +// . % . Print a `%'. +// . . +// . c . The argument is an ASCII character. +// . . +// . x . The argument is a hexadecimal number. The characters used are +// . . 0..9 and a..f. If the flag `l' is not specified, then the +// . . argument is assumed to be an int. +// . . +// . X . The argument is a hexadecimal number. The characters used are +// . . 0..9 and A..F. If the flag `l' is not specified, then the +// . . argument is assumed to be an int. +// . . +// . d . The argument is a decimal number. If the flag `l' is not +// . . specified, then the argument is assumed to be an int. +// . . +// . i . The same as `d'. +// . . +// . s . The argument is a pointer to null-terminated ASCII string. +// . . +// . a . The same as `s'. +// . . +// . S . The argument is a pointer to a null-terminated Unicode string. +// . . +// . g . The argument is a pointer to a GUID structure. The GUID is +// . . printed in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. +// . . +// . G . The argument is a pointer to a GUID structure. The GUID is +// . . printed in the format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX. +// . . +// . r . The argument is an EFI_STATUS value. This value is converted +// . . to a string. +// . . +// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . +// +// NOTE +// All invalid type characters are copied into the result string. +// +// +//************************************************************************* +UINTN Sprintf( char *Buffer, char *Format, ...) +{ + va_list ArgList = va_start(ArgList,Format); + UINTN Ret = Sprintf_va_list( Buffer, Format, ArgList ); + va_end(ArgList); + return Ret; +} + +char* GetStatusCodeString(EFI_STATUS Status){ + static char* EfiSuccess="EFI_SUCCESS"; + + if (Status == 0) return EfiSuccess; + if ((Status & EFI_ERROR_BIT) == 0 ){//warning + if ((Status & PI_WARNING_BIT) == PI_WARNING_BIT ){//PI warning + if (Status >= NUM_OF_PI_WARNINGS) return NULL; + return PiWarningStatus[Status]; + }else{//UEFI warning + if (Status > NUM_OF_EFI_WARNINGS) return NULL; + return EfiWarningStatus[Status-1]; + } + }else{//error + UINTN Index = Status & ~(EFI_ERROR_BIT | PI_ERROR_BIT | OEM_ERROR_BIT); + if ((Status & PI_ERROR_BIT) == PI_ERROR_BIT ){//PI error + if (Index >= NUM_OF_PI_ERRORS) return NULL; + return PiErrorStatus[Index]; + }else if ((Status & OEM_ERROR_BIT) == OEM_ERROR_BIT ){//OEM error + if (Index > NUM_OF_AMI_ERRORS) return NULL; + return AmiErrorStatus[Index-1]; + }else{//UEFI error + if (Index > NUM_OF_EFI_ERRORS) return NULL; + return EfiErrorStatus[Index-1]; + } + + } +} + +//************************************************************************* +// +// Name: Sprintf_s_va_list +// +// Description: +// UINTN Sprintf_s_va_list(OUT CHAR8 *Buffer, IN UINTN BufferSize, +// IN CHAR8 *Format, IN va_list Marker) produces a null-terminated ASCII +// string in the output Buffer of size BufferSize. The ASCII string is +// produced by parsing the format string specified by Format. Arguments are +// pulled from the variable argument list, Marker, based on the contents of +// the format string. The number of ASCII characters in the produced output +// buffer is returned, not including the null-terminator. +// +// Input: +// OUT CHAR8 *Buffer +// Pointer to a null-terminated output ASCII string buffer. User is +// responsible for allocating the necessary memory resources! +// +// IN UINTN BufferSize +// The size, in bytes, of the output Buffer. +// +// IN CHAR8 *Format +// Pointer to a null-terminated format ASCII string. +// +// IN va_list Marker +// Marker for the variable argument list. +// +// Output: +// UINTN number of ASCII characters in the produced output buffer, not +// including the null-terminator. +// +// Modified: +// +// Referrals: +// Sprintf_va_list +// MemCpy +// +// Notes: +// This is a helper function for Sprintf_s. Refer to Sprintf function for +// format string syntax. +// +//************************************************************************* +UINTN Sprintf_s_va_list(char *Buffer, UINTN BufferSize, char *Format, va_list Marker) +{ + char filler; + int width; + char numbuffer[32]; + UINTN strlength; + char *strp = Format; + char *buffp = Buffer; + char *_strp, *str2p; + int radix; + BOOLEAN its_int64; + UINTN n; + + if (Buffer==NULL || Format==NULL) return -1; + //If BuuferSize is 0, no size check required + while(BufferSize!=1 && *strp) { + if (*strp != '%'){ + *buffp++ = *strp++; + BufferSize--; + continue; + } + strp++; //skip % + if (*strp=='%') { + strp++; + *buffp++ = '%'; + BufferSize--; + continue; + } + + filler = ' '; + + //Get flags + if (*strp == '0') { + filler = '0'; + *strp++; + } + + //Get Width + if (*strp == '*') { //width is supplied by argument. + strp++; + width = va_arg(Marker,int); + } else { + width = Strtol(strp,&_strp,10); //If no width, then 0 returned. + strp=_strp; + } + + //Get type. + if (*strp == 's' || *strp == 'a'/*to be compatible with Intel Print library*/) { //string + char *str = va_arg(Marker,char *); + while (*str) { + if ( --BufferSize == 0 ) { + *buffp = 0; // null terminator + return buffp - Buffer; + } + *buffp++ = *str++; + } + ++strp; + continue; + } + + if (*strp == 'S') { // unicode string + CHAR16 *str = va_arg(Marker,CHAR16 *); + while (*str) { + if ( --BufferSize == 0 ) { + *buffp = 0; // null terminator + return buffp - Buffer; + } + *buffp++ = (char)*str++; + } + ++strp; + continue; + } + + if (*strp == 'c') { //character + *buffp++ = va_arg(Marker,char); + ++strp; + continue; + } + + if ((*strp & 0xdf) == 'G') { //'G' or 'g' + EFI_GUID *guid = va_arg(Marker,EFI_GUID*); + CHAR8 *origp = buffp; + + n = Sprintf_s( + buffp, + BufferSize, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], + guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4], + guid->Data4[5], guid->Data4[6], guid->Data4[7] + ); + buffp += n; + if (*strp == 'G') + Strupr(origp); + BufferSize -= n; + ++strp; + continue; + } + + if (*strp == 'r') { + EFI_STATUS Status = va_arg(Marker,EFI_STATUS); + char *StatusCodeString = GetStatusCodeString(Status); + + if (StatusCodeString==NULL) + n = Sprintf_s( buffp, BufferSize, "%s(%X)", EfiUnknown, Status ); + else + n = Sprintf_s( buffp, BufferSize, "%s", StatusCodeString ); + + buffp += n; + BufferSize -= n; + ++strp; + continue; + } + + if (*strp == 'l') { + strp++; + its_int64 = TRUE; + } else + its_int64 = FALSE; + + if (*strp == 'd' || *strp == 'i') + radix = 10; + else if ( (*strp & 0xdf) == 'X' ) + radix = 16; //'X' or 'x' + else + continue; //invalid *strp + + if (its_int64) + I64toa( va_arg(Marker,INT64), numbuffer, radix ); + else + Itoa( va_arg(Marker,int), numbuffer, radix ); + if (*strp == 'X') + Strupr(numbuffer); + + strlength = Strlen(numbuffer); + while ( strlength++ < (unsigned)width ) { + if ( --BufferSize == 0 ) { + *buffp = 0; // null terminator + return buffp - Buffer; + } + *buffp++ = filler; + } + + str2p = numbuffer; + while (*str2p) { + if ( --BufferSize == 0 ) { + *buffp = 0; // null terminator + return buffp - Buffer; + } + *buffp++ = *str2p++; + } + + strp++; + } + + *buffp = 0; + return buffp - Buffer; +} + +//************************************************************************* +// +// +// Name: Sprintf_s +// +// Description: +// UINTN Sprintf_s(OUT CHAR8 *Buffer, IN UINTN BufferSize, IN CHAR8 *Format, +// IN ...) produces a null-terminated ASCII string in the output Buffer of +// size BufferSize. The ASCII string is produced by parsing the format +// string specified by Format. Arguments are pulled from the variable +// argument list based on the contents of the format string. The number of +// ASCII characters in the produced output buffer is returned, not including +// the null-terminator. +// +// Input: +// OUT CHAR8 *Buffer +// Pointer to a null-terminated output ASCII string buffer. User is +// responsible for allocating the necessary memory resources! +// +// IN UINTN BufferSize +// The size, in bytes, of the output Buffer. +// +// IN CHAR8 *Format +// Pointer to a null-terminated format ASCII string. +// +// IN ... +// Variable argument list of data/variables used within the format string. +// +// Output: +// UINTN number of ASCII characters in the produced output buffer, not +// including the null-terminator. +// +// Modified: +// +// Referrals: +// va_start +// Sprintf_s_va_list +// va_end +// +// Notes: +// Refer to Sprintf function for format string syntax. +// +// +//************************************************************************* +UINTN Sprintf_s( char *Buffer, UINTN BufferSize, char *Format, ... ) +{ + va_list ArgList = va_start(ArgList, Format); + UINTN Ret = Sprintf_s_va_list( Buffer, BufferSize, Format, ArgList ); + va_end(ArgList); + return Ret; +} + +//************************************************************************* +// +// Name: Swprintf_va_list +// +// Description: +// UINTN Swprintf_va_list(OUT CHAR16 *buffer, IN CHAR16 *format, +// IN va_list arg) produces a null-terminated Unicode string in the output +// buffer. The Unicode string is produced by parsing the format string +// specified by format. Arguments are pulled from the variable argument list +// specified by arg based on the contents of the format string. The number +// of Unicode characters in the produced output buffer is returned, not +// including the null-terminator. +// +// Input: +// OUT CHAR16 *buffer +// Pointer to a null-terminated output Unicode string buffer. User is +// responsible for allocating the necessary memory resources! +// +// IN CHAR16 *format +// Pointer to a null-terminated format Unicode string. +// +// IN va_list arg +// Marker for the variable argument list. +// +// Output: +// UINTN number of Unicode characters in the produced output buffer, not +// including the null-terminator. +// +// Modified: +// +// Referrals: +// va_arg +// Wcstol +// Swprintf +// Wcsupr +// I64tow +// Itow +// Wcslen +// +// Notes: +// Refer to Sprintf function for format string syntax. +// +//************************************************************************* +UINTN Swprintf_va_list(CHAR16 *buffer, CHAR16 *format, va_list arg) +{ + return Swprintf_s_va_list( buffer, 0, format, arg ); +} + +//************************************************************************* +// +// +// Name: Swprintf +// +// Description: +// UINTN Swprintf(OUT CHAR16 *Buffer, IN CHAR16 *Format, IN ...) produces a +// null-terminated Unicode string in the output Buffer. The Unicode string is +// produced by parsing the format string specified by Format. Arguments are +// pulled from the variable argument list based on the contents of the format +// string. The number of Unicode characters in the produced output buffer is +// returned, not including the null-terminator. +// +// Input: +// OUT CHAR16 *Buffer +// Pointer to a null-terminated output Unicode string buffer. User is +// responsible for allocating the necssary memory resources! +// +// IN CHAR16 *Format +// Pointer to a null-terminated format Unicode string. +// +// IN ... +// Variable arguement list of data/variables used within the format string. +// +// Output: +// UINTN number of Unicode characters in the produced output buffer, not +// including the null-terminator. +// +// Modified: +// +// Referrals: +// va_start +// Swprintf_va_list +// va_end +// +// Notes: +// See Sprintf function for format string details. +// +// +//************************************************************************* +UINTN Swprintf(CHAR16 *Buffer, CHAR16 *Format, ...) +{ + va_list ArgList = va_start(ArgList,Format); + UINTN Ret = Swprintf_va_list(Buffer,Format,ArgList); + va_end(ArgList); + return Ret; +} + +//************************************************************************* +// +// Name: Swprintf_s_va_list +// +// Description: +// UINTN Swprintf_s_va_list(OUT CHAR16 *Buffer, IN UINTN BufferSize, +// IN CHAR16 *Format, IN va_list Marker) produces a null-terminated Unicode +// string in the output Buffer of size BufferSize. The Unicode string is +// produced by parsing the format string specified by Format. Arguments are +// pulled from the variable argument list based on the contents of the format +// string. The number of Unicode characters in the produced output buffer is +// returned, not including the null-terminator. +// +// Input: +// OUT CHAR16 *Buffer +// Pointer to a null-terminated output Unicode string buffer. User is +// responsible for allocating the necessary memory resources! +// +// IN UINTN BufferSize +// The size, in bytes, of the output Buffer. +// +// IN CHAR16 *Format +// Pointer to a null-terminated format Unicode string. +// +// IN va_list Marker +// Marker for the variable argument list. +// +// Output: +// UINTN number of ASCII characters in the produced output buffer, not +// including the null-terminator. +// +// Modified: +// +// Referrals: +// Swprintf_va_list +// MemCpy +// +// Notes: +// This is a helper function for Swprintf_s. Refer to Sprintf function for +// format string syntax. +// +//************************************************************************* +UINTN Swprintf_s_va_list(CHAR16 *Buffer, UINTN BufferSize, CHAR16 *Format, va_list Marker) +{ + CHAR16 filler; + int width; + CHAR16 numbuffer[32]; + UINTN strlength; + CHAR16 *strp = Format; + CHAR16 *buffp = Buffer; + CHAR16 *_strp, *str2p; + int radix; + BOOLEAN its_int64; + UINTN n; + + if (Buffer==NULL || Format==NULL) return -1; + //If BuuferSize is 0, no size check required + while(BufferSize!=1 && *strp) { + if (*strp != '%'){ + *buffp++ = *strp++; + BufferSize--; + continue; + } + strp++; //skip % + if (*strp=='%') { + strp++; + *buffp++ = '%'; + BufferSize--; + continue; + } + + filler = ' '; + + //Get flags + if (*strp == '0') { + filler = '0'; + *strp++; + } + + //Get Width + if (*strp == '*') { //width is supplied by argument. + strp++; + width = va_arg(Marker, int); + } else { + width = Wcstol( strp, &_strp, 10 ); //If no width, then 0 returned. + strp=_strp; + } + + //Get type. + if (*strp == 's') { // unicode string + CHAR16 *str = va_arg(Marker, CHAR16*); + while (*str) { + if ( --BufferSize == 0 ) { + *buffp = 0; // null terminator + return buffp - Buffer; + } + *buffp++ = *str++; + } + ++strp; + continue; + } + + if ( *strp == 'S' || *strp == 'a' /*to be compatible with Intel Print library*/ ) { //string + char *str = va_arg(Marker, char *); + while (*str) { + if ( --BufferSize == 0 ) { + *buffp = 0; // null terminator + return buffp - Buffer; + } + *buffp++ = *str++; + } + ++strp; + continue; + } + + if (*strp == 'c') { //character + *buffp++ = va_arg(Marker, CHAR16); + ++strp; + continue; + } + + if ((*strp & 0xdf) == 'G') { //'G' or 'g' + EFI_GUID *guid = va_arg(Marker, EFI_GUID*); + CHAR16 *origp = buffp; + n = Swprintf_s( + buffp, + BufferSize, + L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], + guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4], + guid->Data4[5], guid->Data4[6], guid->Data4[7] + ); + buffp += n; + if (*strp == 'G') + Wcsupr(origp); + BufferSize -= n; + ++strp; + continue; + } + + if (*strp == 'r') { + EFI_STATUS Status = va_arg(Marker, EFI_STATUS); + char *StatusCodeString = GetStatusCodeString(Status); + + if (StatusCodeString==NULL) + n = Swprintf_s( buffp, BufferSize, L"%S(%X)", EfiUnknown, Status ); + else + n = Swprintf_s( buffp, BufferSize, L"%S", StatusCodeString ); + + buffp += n; + BufferSize -= n; + ++strp; + continue; + } + + if (*strp == 'l') { + strp++; + its_int64 = TRUE; + } else + its_int64 = FALSE; + + if (*strp == 'd' || *strp == 'i') + radix = 10; + else if ((*strp & 0xdf) == 'X') + radix = 16; //'X' or 'x' + else + continue; //invalid *strp + + if (its_int64) + I64tow( va_arg(Marker,INT64), numbuffer, radix ); + else + Itow( va_arg(Marker,int), numbuffer, radix ); + if (*strp == 'X') + Wcsupr(numbuffer); + + strlength = Wcslen(numbuffer); + while ( strlength++ < (unsigned)width ) { + if ( --BufferSize == 0 ) { + *buffp = 0; // null terminator + return buffp - Buffer; + } + *buffp++ = filler; + } + + str2p = numbuffer; + while (*str2p) { + if ( --BufferSize == 0 ) { + *buffp = 0; // null terminator + return buffp - Buffer; + } + *buffp++ = *str2p++; + } + + strp++; + } + + *buffp = 0; + return buffp - Buffer; +} + +//************************************************************************* +// +// +// Name: Swprintf_s +// +// Description: +// UINTN Swprintf_s(OUT CHAR16 *Buffer, IN UINTN BufferSize, +// IN CHAR16 *Format, IN ...) produces a null-terminated Unicode string in +// the output Buffer of size BufferSize. The Unicode string is produced by +// parsing the format string specified by Format. Arguments are pulled from +// the variable argument list based on the contents of the format string. +// The number of Unicode characters in the produced output buffer is +// returned, not including the null-terminator. +// +// Input: +// OUT CHAR16 *Buffer +// Pointer to a null-terminated output Unicode string buffer. User is +// responsible for allocating the necessary memory resources! +// +// IN UINTN BufferSize +// The size, in bytes, of the output Buffer. +// +// IN CHAR16 *Format +// Pointer to a null-terminated format Unicode string. +// +// IN ... +// Variable argument list of data/variables used within the format string. +// +// Output: +// UINTN number of Unicode characters in the produced output buffer, not +// including the null-terminator. +// +// Modified: +// +// Referrals: +// va_start +// Swprintf_s_va_list +// va_end +// +// Notes: +// Refer to Sprintf function for format string syntax. +// +// +//************************************************************************* +UINTN Swprintf_s(CHAR16 *Buffer, UINTN BufferSize, CHAR16 *Format, ...) +{ + va_list ArgList = va_start(ArgList,Format); + UINTN Ret = Swprintf_s_va_list(Buffer,BufferSize,Format,ArgList); + va_end(ArgList); + return Ret; +} +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* diff --git a/Library/Tokens.c b/Library/Tokens.c new file mode 100644 index 0000000..982d7e7 --- /dev/null +++ b/Library/Tokens.c @@ -0,0 +1,522 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Library/Tokens.c 2 9/17/13 10:18p Thomaschen $ +// +// $Revision: 2 $ +// +// $Date: 9/17/13 10:18p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Library/Tokens.c $ +// +// 2 9/17/13 10:18p Thomaschen +// Update for PS2CTL module which labeled 4.6.5_PS2CTL_003. +// +// 1 6/04/13 1:50a Thomaschen +// Fixed for EIP118202. +// +// 23 11/01/12 6:40a Deepthins +// [TAG] EIP101100 +// [Category] Improvement +// [Description] Multi Language is supported in Ps2ctl driver +// [Files] CORE_DXE.sdl, kbc.h, ps2kbd.c and Tokens.c +// +// 22 5/24/12 3:22p Artems +// [TAG] EIP N/A +// [Category] Improvement +// [Description] Graphics console tokens moved from BdsBoard.c to +// tokens.c +// [Files] BdsBoard.c Tokens.c +// +// 21 4/20/12 2:28p Artems +// [TAG] EIP87678 +// [Category] New Feature +// [Description] Selection of image to boot from on flash update boot +// path - either old image (currently in flash) or new one in recovery +// capsule +// [Files] Recovery.c +// DxeIpl.c +// Core.sdl +// Tokens.c +// +// 20 2/01/12 1:57a Deepthins +// [TAG] EIP63116 +// [Category] New Feature +// [Description] PS/2 Keyboard/Mouse IRQ mode generic support +// [Files] Token.c, Ps2main.c, Ps2kbd.c, Mouse.c, kbc.h, kbc.c, +// CORE_DXE.sdl +// +// 19 4/27/11 4:47a Lavanyap +// [TAG] - EIP49407 +// [Category] - IMPROVEMENT +// [Description] - Move the Ps2 driver SDL tokens from Core Source to Core +// Bin,So that we don't need to add Core source for changing the Ps2 +// driver SDL tokens. +// [Files] - Ps2Ctl.sdl, ps2kbd.c, ps2main.c, ps2ctl.h, kbc.c, mouse.c, +// hotkey.c, CORE_DXE.sdl, Tokens.c +// +// 18 1/25/11 12:50p Oleksiyy +// [TAG] EIP42253 +// [Category] New Feature +// [Description] Added support for platforms, where flash part is not +// memory mapped while write enabled, controlled by +// NO_MMIO_FLASH_ACCESS_DURING_UPDATE sdl token. Flash protocol used to +// access flash in that case. +// [Files] NVRAMDXE.c, Flash.c, Tokens.c and Runtime.sdl +// +// 17 9/02/10 3:36p Felixp +// Enhancement(EIP 39460): Runtime Garbage Collection Support. +// NvramRtGarbageCollectionSupport variable is added. +// +// 16 8/23/10 3:29p Felixp +// Enhancement(EIP 29307): HideComPort variable is added. Part of Runtime +// Trace support. +// +// 15 8/20/10 12:48p Felixp +// LZMA compression support: GetDecompressInterface function is added. +// +// 14 11/25/09 1:30p Felixp +// +// 13 11/25/09 1:24p Felixp +// +// 12 11/25/09 1:22p Felixp +// TraceLevelMask constant is added +// +// 11 11/24/09 11:31a Felixp +// DefaultLanguageCode constant is added. +// +// 10 8/25/09 4:12p Felixp +// NvramChecksumSupport constant is added. +// +// 9 7/10/09 9:21a Felixp +// Headers updated +// +// 8 7/10/09 8:54a Felixp +// New NVRAM_MONOTONIC_COUNTER_SUPPORT SDL token is created. +// The token can be used to disable Core NVRAM-based implementation of the +// monotonic counter +// architectural protocol and to use stand alone monotonic counter driver +// instead. +// +// 7 10/09/08 11:47a Felixp +// NvramBackupAddress variable added +// +// 6 8/31/07 9:36a Felixp +// NVRAM code update related changes +// +// 5 3/31/07 1:45p Felixp +// Bug fix: NvramEnd was improperly defined. It caused NVRAM overflaw +// (NVRAM garbage collection never happened). +// +// 4 12/20/06 1:48p Felixp +// FlashBlockSize type changed from UINTN to UINT32 +// +// 2 7/22/05 2:20a Felixp +// NVRAM enclosed into Firmware volume +// +// 1 6/16/05 10:40a Felixp +// +//********************************************************************** +// +// +// Name: Tokens.c +// +// Description: +// This file contains constants and variables corresponding to some of the SDL tokens. +// The constants and variables are used by modules that are distributed in binary +// and cannot directly consume token.h +// +// +//********************************************************************** +#include +#include +#include + +// Constants +const char *sAmiRomFile = CONVERT_TO_STRING(AMI_ROM); + +const UINTN FlashSize = FLASH_SIZE; +const UINT32 FlashBlockSize = FLASH_BLOCK_SIZE; +const UINT32 FlashRetries = FLASH_RETRIES; +const UINTN FlashEmpty = (UINTN)(-FLASH_ERASE_POLARITY); +const UINT32 FlashEmptyNext = (FLASH_ERASE_POLARITY ? 0xffffff : 0); +const UINTN NvramAddress = NVRAM_ADDRESS; +#if FAULT_TOLERANT_NVRAM_UPDATE +const UINTN NvramBackupAddress = NVRAM_BACKUP_ADDRESS; +#else +const UINTN NvramBackupAddress = 0; +#endif +#if RUNTIME_TRACE_SUPPORT +const BOOLEAN HideComPort = TRUE; +#else +const BOOLEAN HideComPort = FALSE; +#endif +const UINTN NvramSize = NVRAM_SIZE; +const BOOLEAN NvSimulation = NV_SIMULATION; +const UINT32 NvramHeaderLength = NVRAM_HEADER_SIZE; +const BOOLEAN NvramMonotonicCounterSupport = NVRAM_MONOTONIC_COUNTER_SUPPORT; +const BOOLEAN NvramChecksumSupport = NVRAM_RECORD_CHECKSUM_SUPPORT; + +#ifdef DEFAULT_LANGUAGE_CODE +const char *DefaultLanguageCode = CONVERT_TO_STRING(DEFAULT_LANGUAGE_CODE); +#endif +const UINT32 TraceLevelMask = TRACE_LEVEL_MASK; + +// Variables +#define FLASH_DEVICE_BASE_ADDRESS (0xFFFFFFFF-FLASH_SIZE+1) +UINTN FlashDeviceBase = FLASH_DEVICE_BASE_ADDRESS; +UINTN FwhFeatureSpaceBase = FLASH_DEVICE_BASE_ADDRESS & ~(UINTN)0x400000; + +#if NVRAM_RT_GARBAGE_COLLECTION_SUPPORT +const BOOLEAN NvramRtGarbageCollectionSupport = NVRAM_RT_GARBAGE_COLLECTION_SUPPORT; +#else +const BOOLEAN NvramRtGarbageCollectionSupport = 0; +#endif +#if NO_MMIO_FLASH_ACCESS_DURING_UPDATE +const BOOLEAN FlashNotMemoryMapped = NO_MMIO_FLASH_ACCESS_DURING_UPDATE; +#else +const BOOLEAN FlashNotMemoryMapped = 0; +#endif + +#ifdef USE_RECOVERY_IMAGE_ON_FLASH_UPDATE +const BOOLEAN UseNewImage = USE_RECOVERY_IMAGE_ON_FLASH_UPDATE; +#else +const BOOLEAN UseNewImage = TRUE; +#endif + +typedef struct _TEXT_MODE { + INT32 ModeNum; + INT32 Col; + INT32 Row; + UINT32 VideoCol; // horizontal pixels + UINT32 VideoRow; // vertical pixels +} TEXT_MODE; + +const TEXT_MODE TextModeArray[] = {GC_MODE_LIST}; +const INT32 MaxTextMode=(sizeof(TextModeArray)/sizeof(TEXT_MODE)); + + +//Ps2Ctl driver global variables + +// +//---------------------------------------------------------------------------- +// Name: KbdIrqSupport +// +// Description: Variable to replace KB_IRQ_SUPPORT token. +// +// Notes: BOOLEAN +// +//---------------------------------------------------------------------------- +// +BOOLEAN KbdIrqSupport = +#ifdef KB_IRQ_SUPPORT + KB_IRQ_SUPPORT +#else + 0 +#endif + ; +// +//---------------------------------------------------------------------------- +// Name: MsIrqSupport +// +// Description: Variable to replace MS_IRQ_SUPPORT token. +// +// Notes: BOOLEAN +// +//---------------------------------------------------------------------------- +// +BOOLEAN MsIrqSupport = +#ifdef MS_IRQ_SUPPORT + MS_IRQ_SUPPORT +#else + 0 +#endif + ; +// +//---------------------------------------------------------------------------- +// Name: Ps2MouseSupport +// +// Description: Variable to replace PS2MOUSE_SUPPORT token. +// +// Notes: BOOLEAN +// +//---------------------------------------------------------------------------- +// +BOOLEAN Ps2MouseSupport = +#ifdef PS2MOUSE_SUPPORT + PS2MOUSE_SUPPORT +#else + 0 +#endif + ; +// +//---------------------------------------------------------------------------- +// Name: Ps2KbdSupport +// +// Description: Variable to replace PS2KBD_SUPPORT token. +// +// Notes: BOOLEAN +// +//---------------------------------------------------------------------------- +// +BOOLEAN Ps2KbdSupport = +#ifdef PS2KBD_SUPPORT +PS2KBD_SUPPORT +#else + 0 +#endif + ; +// +//---------------------------------------------------------------------------- +// Name: KbRdBeforeInstall +// +// Description: Variable to replace KBD_READ_BEFORE_INSTALL token. +// +// Notes: BOOLEAN +// +//---------------------------------------------------------------------------- +// +BOOLEAN KbRdBeforeInstall = +#ifdef KBD_READ_BEFORE_INSTALL + KBD_READ_BEFORE_INSTALL +#else + 0 +#endif + ; +// +//---------------------------------------------------------------------------- +// Name: KbcAutoDetectPorts +// +// Description: Variable to replace KBC_AUTODETECT_PORTS token. +// +// Notes: BOOLEAN +// +//---------------------------------------------------------------------------- +// +BOOLEAN KbcAutoDetectPorts = +#ifdef KBC_AUTODETECT_PORTS +KBC_AUTODETECT_PORTS +#else + 0 +#endif + ; +// +//---------------------------------------------------------------------------- +// Name: BlockKbcPin2223Bit +// +// Description: Variable to replace BLOCK_KBC_PIN_22_23_BIT token. +// +// Notes: BOOLEAN +// +//---------------------------------------------------------------------------- +// +BOOLEAN BlockKbcPin2223Bit = +#ifdef BLOCK_KBC_PIN_22_23_BIT +BLOCK_KBC_PIN_22_23_BIT +#else + 0 +#endif + ; +// +//---------------------------------------------------------------------------- +// Name: LedsAtStartup +// +// Description: Variable to replace LEDS_AT_STARTUP token. +// +// Notes: UINT8 +// +//---------------------------------------------------------------------------- +// +UINT8 LedsAtStartup = +#ifdef LEDS_AT_STARTUP +LEDS_AT_STARTUP +#else + 0 +#endif + ; +// +//---------------------------------------------------------------------------- +// Name: MaxHotKeys +// +// Description: Variable to replace MAX_HOTKEYS token. +// +// Notes: UINT8 +// +//---------------------------------------------------------------------------- +// +UINT8 MaxHotKeys = +#ifdef MAX_HOTKEYS +MAX_HOTKEYS +#else + 0 +#endif + ; +// +//---------------------------------------------------------------------------- +// Name: InitDefaultHotKeys +// +// Description: Variable to replace INIT_DEFAULT_HOTKEYS token. +// +// Notes: BOOLEAN +// +//---------------------------------------------------------------------------- +// +BOOLEAN InitDefaultHotKeys = +#ifdef INIT_DEFAULT_HOTKEYS +INIT_DEFAULT_HOTKEYS +#else + 0 +#endif + ; +// +//---------------------------------------------------------------------------- +// Name: KbcBasicAssuranceTest +// +// Description: Variable to replace KBC_BASIC_ASSURANCE_TEST token. +// +// Notes: BOOLEAN +// +//---------------------------------------------------------------------------- +// +BOOLEAN KbcBasicAssuranceTest = +#ifdef KBC_BASIC_ASSURANCE_TEST +KBC_BASIC_ASSURANCE_TEST +#else + 0 +#endif + ; +// +//---------------------------------------------------------------------------- +// Name: DetectPs2KeyboardValue +// +// Description: Variable to replace DETECT_PS2_KEYBOARD token. +// +// Notes: BOOLEAN +// +//---------------------------------------------------------------------------- +// +BOOLEAN DetectPs2KeyboardValue = +#ifdef DETECT_PS2_KEYBOARD +DETECT_PS2_KEYBOARD +#else + 0 +#endif + ; +// +//---------------------------------------------------------------------------- +// Name: DetectPs2MouseValue +// +// Description: Variable to replace DETECT_PS2_MOUSE token. +// +// Notes: BOOLEAN +// +//---------------------------------------------------------------------------- +// +BOOLEAN DetectPs2MouseValue = +#ifdef DETECT_PS2_MOUSE +DETECT_PS2_MOUSE +#else + 0 +#endif + ; +// +//---------------------------------------------------------------------------- +// Name: InstallKeyboardMouseAlways +// +// Description: Variable to replace INSTALL_KEYBOARD_MOUSE_ALWAYS token. +// +// Notes: BOOLEAN +// +//---------------------------------------------------------------------------- +// +BOOLEAN InstallKeyboardMouseAlways = +#ifdef INSTALL_KEYBOARD_MOUSE_ALWAYS +INSTALL_KEYBOARD_MOUSE_ALWAYS +#else + 0 +#endif + ; + +// +//---------------------------------------------------------------------------- +// Name: IbFreeTimeoutValue +// +// Description: Variable to replace IBFREE_TIMEOUT token. +// +// Notes: UINT32 +// +//---------------------------------------------------------------------------- +// +UINT32 IbFreeTimeoutValue = +#ifdef IBFREE_TIMEOUT +IBFREE_TIMEOUT +#else + 0 +#endif + ; + +// +//---------------------------------------------------------------------------- +// Name: IbMaxFreeTimeoutValue +// +// Description: Variable to replace MAXIMUM_TIMEOUT_FOR_IBFREE token. +// +// Notes: UINT32 +// +//---------------------------------------------------------------------------- +// +UINT32 IbFreeMaxTimeoutValue = +#ifdef MAXIMUM_TIMEOUT_FOR_IBFREE +MAXIMUM_TIMEOUT_FOR_IBFREE +#else + 0 +#endif + ; + +//Decompression +BOOLEAN GetDecompressInterface( + UINT8 CompressionType, GET_INFO *GetInfoPtr, DECOMPRESS *DecompressPtr +) +{ + if (CompressionType==EFI_STANDARD_COMPRESSION){ + *GetInfoPtr=GetInfo; + *DecompressPtr=Decompress; + return TRUE; + } +#if LZMA_SUPPORT==1 + else if (CompressionType==EFI_CUSTOMIZED_COMPRESSION){ + *GetInfoPtr=LzmaGetInfo; + *DecompressPtr=LzmaDecompress; + return TRUE; + } +#endif + return FALSE; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** -- cgit v1.2.3