summaryrefslogtreecommitdiff
path: root/Library
diff options
context:
space:
mode:
authorraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
committerraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
commitb7c51c9cf4864df6aabb99a1ae843becd577237c (patch)
treeeebe9b0d0ca03062955223097e57da84dd618b9a /Library
downloadzprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'Library')
-rw-r--r--Library/AcpiRes.c2309
-rw-r--r--Library/AmiBufferValidationLib.chmbin0 -> 42727 bytes
-rw-r--r--Library/AmiBufferValidationLib.cif13
-rw-r--r--Library/AmiBufferValidationLib.mak64
-rw-r--r--Library/AmiBufferValidationLib.sdl16
-rw-r--r--Library/AmiDxeLib.cif13
-rw-r--r--Library/AmiDxeLib.mak93
-rw-r--r--Library/AmiDxeLib.sdl20
-rw-r--r--Library/AmiLib.chmbin0 -> 203333 bytes
-rw-r--r--Library/AmiLib.cif17
-rw-r--r--Library/AmiLib.sdl9
-rw-r--r--Library/AmiPeiLib.cif10
-rw-r--r--Library/AmiPeiLib.mak96
-rw-r--r--Library/AmiPeiLib.sdl28
-rw-r--r--Library/Debug.c311
-rw-r--r--Library/Decompress.c1046
-rw-r--r--Library/EfiDBE.c891
-rw-r--r--Library/EfiLib.c4779
-rw-r--r--Library/IO.c664
-rw-r--r--Library/LibSrc.cif14
-rw-r--r--Library/LibSrc.sdl10
-rw-r--r--Library/Library.cif10
-rw-r--r--Library/Library.sdl36
-rw-r--r--Library/LinkedList.c355
-rw-r--r--Library/LzmaDecode.c1592
-rw-r--r--Library/Memory.c340
-rw-r--r--Library/Misc.c220
-rw-r--r--Library/PELoader.c800
-rw-r--r--Library/PeiLib.c1132
-rw-r--r--Library/Print.c414
-rw-r--r--Library/SmmAmiBufferValidationLib.c239
-rw-r--r--Library/StdLibC.c1831
-rw-r--r--Library/Tokens.c522
33 files changed, 17894 insertions, 0 deletions
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.
+//*************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: AcpiRes.c
+//
+// Description:
+// Implementation of ASL MACROs for ResourceTemplate. See ACPI 2.0
+// specification section 16.2.4.
+//
+//<AMI_FHDR_END>
+//*************************************************************************
+#include <AmiDxeLib.h>
+#include <AcpiRes.h>
+#include <Protocol\AcpiSupport.h>
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: ASLM_IRQ
+//
+// Description:
+// VOID* ASLM_IRQ(IN UINT8 dsc_cnt, IN UINT8 ll, IN UINT8 he,
+// IN UINT8 shr, IN ...) generates a short IRQ descriptor and returns its
+// address. User is responsible for freeing the returned memory.
+//
+// Input:
+// IN UINT8 dsc_cnt
+// Number of IRQ numbers in the list.
+//
+// IN UINT8 ll
+// IRQ flag. 0 = active-high, 1 = active-low.
+//
+// IN UINT8 he
+// IRQ flag. 0 = level-triggered, 1 = edge-triggered.
+//
+// IN UINT8 shr
+// IRQ flag. 0 = not interrupt shareable, 1 = interrupt shareable.
+//
+// IN ...
+// List of IRQ numbers. Valid values: 0-15.
+//
+// Output:
+// VOID* address of the created IRQ descriptor. User is responsible for
+// freeing the returned memory.
+//
+// Modified:
+//
+// Referrals:
+// Malloc
+// va_start
+// va_arg
+// va_end
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID *ASLM_IRQ(UINT8 dsc_cnt, UINT8 ll, UINT8 he, UINT8 shr, ... )
+{
+ UINT8 i;
+ UINT16 irq=0;
+ va_list marker;
+ UINT32 sz=sizeof(ASLR_IRQ);
+ ASLR_IRQ *rb=(ASLR_IRQ*)Malloc(sz);
+//------------------------------
+
+ if (!rb)return NULL;
+
+ pBS->SetMem(rb,sz,0);
+
+ //Update descriptor Header
+ rb->Hdr.Length=3;//sizeof(ASLR_IRQ)-sizeof(ASLRF_S_HDR);
+ rb->Hdr.Name=ASLV_RT_IRQ;
+ rb->Hdr.Type=ASLV_SMALL_RES;
+
+ //Update descriptor Body
+ rb->Flags._LL=ll;
+ rb->Flags._HE=he;
+ rb->Flags._SHR=shr;
+
+ va_start(marker, shr);
+
+ for (i=0; i<dsc_cnt; i++)
+ {
+ irq|=(1<<va_arg(marker, UINT8));
+ }
+
+ va_end(marker);
+ rb->_INT=irq;
+ return rb;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: ASLM_IRQNoFlags
+//
+// Description:
+// VOID* ASLM_IRQNoFlags(IN UINT8 dsc_cnt, IN ...) generates a short IRQ
+// descriptor without an optional IRQ information byte and returns its
+// address. User is responsible for freeing the returned memory.
+//
+// Input:
+// IN UINT8 dsc_cnt
+// Number of IRQ numbers in the list.
+//
+// IN ...
+// List of IRQ numbers. Valid values: 0-15.
+//
+// Output:
+// VOID* address of the created IRQ descriptor. User is responsible for
+// freeing the returned memory.
+//
+// Modified:
+//
+// Referrals:
+// Malloc
+// va_start
+// va_arg
+// va_end
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID *ASLM_IRQNoFlags(UINT8 dsc_cnt, ... )
+{
+ UINT8 i;
+ va_list marker;
+ UINT16 irq=0;
+ UINT32 sz=sizeof(ASLR_IRQNoFlags);
+ ASLR_IRQNoFlags *rb=(ASLR_IRQNoFlags*)Malloc(sz);
+//------------------------------
+
+ if (!rb)return NULL;
+
+ pBS->SetMem(rb,sz,0);
+
+ //Update descriptor Header
+ rb->Hdr.Length=2;//sizeof(ASLR_IRQNoFlags)-sizeof(ASLRF_S_HDR);
+ rb->Hdr.Name=ASLV_RT_IRQ;
+ rb->Hdr.Type=ASLV_SMALL_RES;
+
+ va_start(marker, dsc_cnt);
+
+ for (i=0; i<dsc_cnt; i++)
+ {
+ irq|=(1<<va_arg(marker, UINT8));
+ }
+
+ va_end(marker);
+ rb->_INT=irq;
+ return rb;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: ASLM_DMA
+//
+// Description:
+// VOID* ASLM_DMA(IN UINT8 dsc_cnt, IN UINT8 typ, IN UINT8 bm, IN UINT8 siz,
+// IN ...) generates a short DMA descriptor and returns its address. User is
+// responsible for freeing the returned memory.
+//
+// Input:
+// IN UINT8 dsc_cnt
+// Number of channel numbers in the list.
+//
+// IN UINT8 typ
+// DMA channel speed. Valid values are:
+// ASLV_Compatibility, ASLV_TypeA, ASLV_TypeB, ASLV_TypeF
+//
+// IN UINT8 bm
+// BusMaster or NotBusMaster. 0 defaults to BusMaster.
+//
+// IN UINT8 siz
+// Transfer size. Valid values are:
+// Transfer8, Transfer16, Transfer8_16
+//
+// IN ...
+// List of channel numbers. Valid values are 0-7.
+//
+// Output:
+// VOID* address of the created DMA descriptor. User is responsible for
+// freeing the returned memory.
+//
+// Modified:
+//
+// Referrals:
+// Malloc
+// va_start
+// va_arg
+// va_end
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID *ASLM_DMA(UINT8 dsc_cnt, UINT8 typ, UINT8 bm, UINT8 siz, ... )
+{
+ UINT8 i, dma=0;
+ va_list marker;
+ UINT32 sz=sizeof(ASLR_DMA);
+ ASLR_DMA *rb=(ASLR_DMA*)Malloc(sz);
+//------------------------------
+
+ if (!rb)return NULL;
+
+ pBS->SetMem(rb,sz,0);
+
+ //Update descriptor Header
+ rb->Hdr.Length=sizeof(ASLR_DMA)-sizeof(ASLRF_S_HDR);
+ rb->Hdr.Name=ASLV_RT_DMA;
+ rb->Hdr.Type=ASLV_SMALL_RES;
+
+ //Update descriptor Body
+ rb->Flags._TYP=typ;
+ rb->Flags._BM=bm;
+ rb->Flags._SIZ=siz;
+
+ va_start(marker, siz);
+
+ for (i=0; i<dsc_cnt; i++)
+ {
+ dma|=(1<<va_arg(marker, UINT8));
+ }
+
+ va_end(marker);
+ rb->_DMA=dma;
+
+ return rb;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: ASLM_StartDependentFn
+//
+// Description:
+// VOID* ASLM_StartDependentFn(IN UINT8 dsc_cnt, IN UINT8 pComp,
+// IN UINT8 pPerf, IN ...) generates a Start-Dependent Function descriptor
+// with the optional priority byte and returns its address. User is
+// responsible for freeing the returned memory.
+//
+// Input:
+// IN UINT8 dsc_cnt
+// Number of items in the descriptor list.
+//
+// IN UINT8 pComp
+// Compatibility priority. Valid values are 0-2.
+//
+// IN UINT8 pPerf
+// Performance/robustness priority. Valid values are 0-2.
+//
+// IN ...
+// List of descriptors for this dependent function.
+//
+// Output:
+// VOID* address of the created Start-Dependent Function descriptor. User
+// is responsible for freeing the returned memory.
+//
+// Modified:
+//
+// Referrals:
+// MallocZ
+// Malloc
+// va_start
+// va_arg
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID *ASLM_StartDependentFn(UINT8 dsc_cnt,UINT8 pComp,UINT8 pPerf, ...)
+{
+ UINT8 i;
+ va_list marker;
+ UINT32 sz=sizeof(EFI_ASL_DepFn)+sizeof(ASLR_StartDependentFn);
+ EFI_ASL_DepFn *rb=(EFI_ASL_DepFn*)MallocZ(sz);
+
+//--------------------------------------------
+ if (!rb)return NULL;
+
+ rb->DepFn=(rb+1);
+ ((ASLR_StartDependentFn*)rb->DepFn)->Hdr.Length=sizeof(ASLR_StartDependentFn)-sizeof(ASLRF_S_HDR);
+ ((ASLR_StartDependentFn*)rb->DepFn)->Hdr.Name=ASLV_RT_StartDependentFn;
+ ((ASLR_StartDependentFn*)rb->DepFn)->Hdr.Type=ASLV_SMALL_RES;
+ ((ASLR_StartDependentFn*)rb->DepFn)->_PRI._CMP=pComp;
+ ((ASLR_StartDependentFn*)rb->DepFn)->_PRI._PRF=pPerf;
+
+ rb->DepRes.Items=Malloc(sizeof(ASLR_HDR*)*dsc_cnt);
+
+ if (!rb->DepRes.Items) return NULL;
+
+ rb->DepRes.InitialCount=dsc_cnt;
+ rb->DepRes.ItemCount=dsc_cnt;
+ va_start(marker, pPerf);
+
+ for (i=0; i<dsc_cnt; i++) rb->DepRes.Items[i]=va_arg(marker, VOID*);
+
+ return rb;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: ASLM_StartDependentFnNoPri
+//
+// Description:
+// VOID* ASLM_StartDependentFnNoPri(IN UINT8 dsc_cnt, IN ...) generates a
+// Start-Dependent Function descriptor without the optional priority byte and
+// returns its address. User is responsible for freeing the returned memory.
+//
+// Input:
+// IN UINT8 dsc_cnt
+// Number of items in the descriptor list.
+//
+// IN ...
+// List of descriptors for this dependent function.
+//
+// Output:
+// VOID* address of the created Start-Dependent Function descriptor. User
+// is responsible for freeing the returned memory.
+//
+// Modified:
+//
+// Referrals:
+// MallocZ
+// Malloc
+// va_start
+// va_arg
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID *ASLM_StartDependentFnNoPri(UINT8 dsc_cnt, ...)
+{
+ UINT8 i;
+ va_list marker;
+ UINT32 sz=sizeof(EFI_ASL_DepFn)+sizeof(ASLR_StartDependentFnNoPri);
+ EFI_ASL_DepFn *rb=(EFI_ASL_DepFn*)MallocZ(sz);
+
+//--------------------------------------------
+ if (!rb)return NULL;
+
+ rb->DepFn=(rb+1);
+ ((ASLR_StartDependentFnNoPri*)rb->DepFn)->Length=sizeof(ASLR_StartDependentFnNoPri)-sizeof(ASLRF_S_HDR);
+ ((ASLR_StartDependentFnNoPri*)rb->DepFn)->Name=ASLV_RT_StartDependentFn;
+ ((ASLR_StartDependentFnNoPri*)rb->DepFn)->Type=ASLV_SMALL_RES;
+
+ rb->DepRes.Items=Malloc(sizeof(ASLR_HDR*)*dsc_cnt);
+
+ if (!rb->DepRes.Items) return NULL;
+
+ rb->DepRes.InitialCount=dsc_cnt;
+ rb->DepRes.ItemCount=dsc_cnt;
+
+ va_start(marker, dsc_cnt);
+
+ for (i=0; i<dsc_cnt; i++) rb->DepRes.Items[i]=va_arg(marker, VOID*);
+
+ return rb;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: ASLM_IO
+//
+// Description:
+// VOID* ASLM_IO(IN UINT8 dec, IN UINT16 min, IN UINT16 max, IN UINT8 aln,
+// IN UINT8 len) generates a short I/O descriptor and returns its address.
+// User is responsible for freeing the returned memory.
+//
+// Input:
+// IN UINT8 dec
+// Decode value. Valid values are: ASLV_Decode16, ASLV_Decode10.
+//
+// IN UINT16 min
+// Address minimum.
+//
+// IN UINT16 max
+// Address maximum.
+//
+// IN UINT8 aln
+// Base alignment.
+//
+// IN UINT8 len
+// Range length.
+//
+// Output:
+// VOID* address of the created I/O descriptor. User is responsible for
+// freeing the returned memory.
+//
+// Modified:
+//
+// Referrals:
+// MallocZ
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID *ASLM_IO(UINT8 dec,UINT16 min,UINT16 max,UINT8 aln,UINT8 len)
+{
+ ASLR_IO *rb=(ASLR_IO*)MallocZ(sizeof(ASLR_IO));
+
+//------------------------------------------
+ if (!rb)return NULL;
+
+ rb->Hdr.Length=sizeof(ASLR_IO)-sizeof(ASLRF_S_HDR);
+ rb->Hdr.Name=ASLV_RT_IO;
+ rb->Hdr.Type=ASLV_SMALL_RES;
+
+ rb->_DEC=dec;
+ rb->_MIN=min;
+ rb->_MAX=max;
+ rb->_ALN=aln;
+ rb->_LEN=len;
+
+ return rb;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: ASLM_FixedIO
+//
+// Description:
+// VOID* ASLM_FixedIO(IN UINT16 bas, IN UINT8 len) generates a short fixed
+// I/O descriptor and returns its address. User is responible for freeing
+// the returned memory.
+//
+// Input:
+// IN UINT16 bas
+// Address base.
+//
+// IN UINT8 len
+// Range length.
+//
+// Output:
+// VOID* address of the created fixed I/O descriptor. User is responsible
+// for freeing the returned memory.
+//
+// Modified:
+//
+// Referrals:
+// MallocZ
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID *ASLM_FixedIO(UINT16 bas, UINT8 len)
+{
+ ASLR_FixedIO *rb=(ASLR_FixedIO*)MallocZ(sizeof(ASLR_FixedIO));
+
+//------------------------------------------
+ if (!rb)return NULL;
+
+ rb->Hdr.Length=sizeof(ASLR_FixedIO)-sizeof(ASLRF_S_HDR);
+ rb->Hdr.Name=ASLV_RT_FixedIO;
+ rb->Hdr.Type=ASLV_SMALL_RES;
+
+ rb->_BAS=bas;
+ rb->_LEN=len;
+
+ return rb;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: ASLM_VendorShort
+//
+// Description:
+// VOID* ASLM_VendorShort(IN UINT8 byte_cnt, IN ...) generates a short
+// Vendor-Defined descriptor and returns its address. User is responsible
+// for freeing the returned memory.
+//
+// Input:
+// IN UINT8 byte_cnt
+// Number of bytes in the list. Must be less than 8.
+//
+// IN ...
+// List of byte expressions for the descriptor. Must be less than 8
+// elements.
+//
+// Output:
+// VOID* address of the created Vendor-Defined descriptor. User is
+// responsible for freeing the returned memory.
+//
+// Modified:
+//
+// Referrals:
+// MallocZ
+// va_start
+// va_arg
+// va_end
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID *ASLM_VendorShort(UINT8 byte_cnt, ...)
+{
+ UINT8 i;
+ va_list marker;
+ UINT32 sz= sizeof(ASLR_VendorShort)+byte_cnt;
+ ASLR_VendorShort *rb=(ASLR_VendorShort*)MallocZ(sz);
+ UINT8 *bb=(UINT8*)rb+1;
+//------------------------------
+
+ if (!rb)return NULL;
+
+ rb->Length=byte_cnt;
+ rb->Name=ASLV_RT_VendorShort;
+ rb->Type=ASLV_SMALL_RES;
+
+ va_start(marker, byte_cnt);
+
+ //Update descriptor Body
+ for (i=0; i<byte_cnt; i++)bb[i]=va_arg(marker, UINT8);
+
+ va_end(marker);
+
+ return rb;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: ASLM_Memory24
+//
+// Description:
+// VOID* ASLM_Memory24(IN UINT8 rw, IN UINT8 min, IN UINT8 max,
+// IN UINT8 aln, IN UINT8 len) generates a long 24-bit memory descriptor and
+// returns its address. User is responsible for freeing the returned memory.
+//
+// Input:
+// IN UINT8 rw
+// Write protection flag. Valid values: ASLV_ReadOnly, ASLV_ReadWrite.
+//
+// IN UINT8 min
+// Minimum base memory address [23:8].
+//
+// IN UINT8 max
+// Maximum base memory address [23:8].
+//
+// IN UINT8 aln
+// Base alignment.
+//
+// IN UINT8 len
+// Range length.
+//
+// Output:
+// VOID* address of the created long 24-bit memory descriptor. User is
+// responsible for freeing the returned memory.
+//
+// Modified:
+//
+// Referrals:
+// MallocZ
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID *ASLM_Memory24(UINT8 rw,UINT8 min, UINT8 max, UINT8 aln, UINT8 len)
+{
+ ASLR_Memory24 *rb=(ASLR_Memory24*)MallocZ(sizeof(ASLR_Memory24));
+
+//------------------------------------------
+ if (!rb)return NULL;
+
+ rb->Hdr.Length=sizeof(ASLR_Memory24)-sizeof(ASLRF_S_HDR);
+ rb->Hdr.Name=ASLV_RT_Memory24;
+ rb->Hdr.Type=ASLV_SMALL_RES;
+
+ rb->_RW=rw;
+ rb->_MIN=min;
+ rb->_MAX=max;
+ rb->_ALN=aln;
+ rb->_LEN=len;
+
+ return rb;
+
+}
+
+//----------------------------------------------------------------------
+// Methods Implementation for T_ITEM_LIST object
+//----------------------------------------------------------------------
+
+#define LST_INIT_COUNT 10 //initial value
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: reallocItemLst
+//
+// Description:
+// EFI_STATUS reallocItemLst(IN T_ITEM_LIST *Lst) is an internal worker
+// function which reallocates space for a T_ITEM_LIST.Items[] array.
+//
+// Input:
+// IN T_ITEM_LIST *Lst
+// List which needs its Items array reallocated.
+//
+// Output:
+// EFI_OUT_OF_RESOURCES, if allocation failed.
+// Otherwise, EFI_SUCCESS.
+//
+// Modified:
+//
+// Referrals:
+// MallocZ
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_STATUS reallocItemLst(T_ITEM_LIST *Lst)
+{
+ UINTN sz=0;
+ VOID *nrl=NULL; //new resource list pointer;
+//---------------------------------------------
+
+ // if Initial count has not been initialized;
+ if (Lst->InitialCount==0) sz=LST_INIT_COUNT*sizeof(VOID*);
+ else
+ {
+ //or Initial Count was initialized but memory fot Items[] array was not allocated
+ if (Lst->InitialCount && !Lst->Items) sz=Lst->InitialCount*sizeof(VOID*);
+ else
+ {
+ //or if we at the end or near the end of the Items[] array list
+ if ((INTN)Lst->ItemCount > (INTN)(Lst->InitialCount-1))
+ sz=(Lst->InitialCount+LST_INIT_COUNT)*sizeof(VOID*);
+ }
+ }
+
+ if (sz)
+ {
+ nrl=MallocZ(sz);
+
+ if (!nrl) return EFI_OUT_OF_RESOURCES;
+
+ pBS->CopyMem((VOID*)nrl,(VOID*)Lst->Items,sizeof(VOID*)*Lst->ItemCount);
+ //Free Buffer of previouse ChildList...
+ pBS->FreePool((VOID*)Lst->Items);
+
+ //Make it point to a new ChildList
+ Lst->Items=nrl;
+ Lst->InitialCount=sz/sizeof(VOID*);
+ }
+
+ return EFI_SUCCESS;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: InsertItemLst
+//
+// Description:
+// EFI_STATUS InsertItemLst(IN T_ITEM_LIST *Lst, IN VOID *pRes,
+// IN UINTN ItemIndex) inserts the provided item pointed to by pRes into the
+// provided Lst at index ItemIndex.
+//
+// Input:
+// IN T_ITEM_LIST *Lst
+// List to be inserted into.
+//
+// IN VOID *pRes
+// Pointer to object to place in list.
+//
+// IN UINTN ItemIndex
+// Index in list to place the object pointed to by pRes.
+//
+// Output:
+// EFI_INVALID_PARAMETER, if the ItemIndex value is invalid.
+// EFI_OUT_OF_RESOURCES, if there is not enough memory for the new object.
+// Otherwise, EFI_SUCCESS.
+//
+// Modified:
+//
+// Referrals:
+// reallocItemLst
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_STATUS InsertItemLst(T_ITEM_LIST *Lst, VOID* pRes, UINTN ItemIndex)
+{
+ INTN i;
+
+//----------------
+ if (!Lst->ItemCount && Lst->ItemCount<ItemIndex) return EFI_INVALID_PARAMETER;
+
+ //Check if Items[] array can accomodate a new child...
+ if (EFI_ERROR(reallocItemLst(Lst)))return EFI_OUT_OF_RESOURCES;
+
+ //Shift items after Index forward
+ for (i=(INTN)Lst->ItemCount-1; i>=(INTN)ItemIndex; i--) Lst->Items[i+1]=Lst->Items[i];
+
+ //fill Item address we are inserting
+ Lst->Items[ItemIndex]=pRes;
+ //Adjust Item Count
+ Lst->ItemCount++;
+ return EFI_SUCCESS;
+}
+
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: DeleteItemLst
+//
+// Description:
+// EFI_STATUS DeleteItemLst(IN T_ITEM_LIST *Lst, IN UINTN ItemIndex,
+// IN BOOLEAN FreeData) deletes the object stored at the provided ItemIndex
+// in Lst. Frees the memory associated with the object pointer if FreeData
+// is TRUE.
+//
+// Input:
+// IN T_ITEM_LIST *Lst
+// List to be deleted from.
+//
+// IN UINTN ItemIndex
+// Index inside Lst->Items to be deleted.
+//
+// IN BOOLEAN FreeData
+// TRUE will free the memory associated with the deleted object.
+//
+// Output:
+// EFI_INVALID_PARAMETER, if the provided ItemIndex is invalid.
+// Otherwise, EFI_SUCCESS.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_STATUS DeleteItemLst(T_ITEM_LIST *Lst, UINTN ItemIndex, BOOLEAN FreeData)
+{
+ UINTN i;
+
+//----------------
+ if (!Lst->ItemCount || Lst->ItemCount<=ItemIndex) return EFI_INVALID_PARAMETER;
+
+ //Free Data associated with Iterm if requested;
+ if (FreeData)pBS->FreePool(Lst->Items[ItemIndex]);
+
+ //Shift items after ItemIndex backwards
+ for (i=ItemIndex; i<Lst->ItemCount-1; i++) Lst->Items[i]=Lst->Items[i+1];
+
+ //Adjust Item Count
+ Lst->ItemCount--;
+ return EFI_SUCCESS;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: AppendItemLst
+//
+// Description:
+// EFI_STATUS AppendItemLst(IN T_ITEM_LIST *Lst, IN VOID *pRes) appends the
+// provided object to Lst.
+//
+// Input:
+// IN T_ITEM_LIST *Lst
+// List to be appended to.
+//
+// IN VOID *pRes
+// Object to be appended.
+//
+// Output:
+// EFI_OUT_OF_RESOURCES, if memory allocation fails.
+// Otherwise, EFI_SUCCESS.
+//
+// Modified:
+//
+// Referrals:
+// reallocItemLst
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_STATUS AppendItemLst(T_ITEM_LIST *Lst, VOID* pRes )
+{
+ //Check if Items[] array can accomodate a new child...
+ if (EFI_ERROR(reallocItemLst(Lst)))return EFI_OUT_OF_RESOURCES;
+
+ Lst->Items[Lst->ItemCount]=pRes;
+ Lst->ItemCount++;
+
+ return EFI_SUCCESS;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: ClearItemLst
+//
+// Description:
+// VOID ClearItemLst(IN T_ITEM_LIST *Lst, IN BOOLEAN FreeData) clears all
+// the items of Lst. If FreeData is TRUE, frees all the memory associated
+// with the stored objects.
+//
+// Input:
+// IN T_ITEM_LIST *Lst
+// List to be cleared.
+//
+// IN BOOLEAN FreeData
+// If TRUE, all objects are freed.
+//
+// Output:
+// VOID.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID ClearItemLst(T_ITEM_LIST *Lst, BOOLEAN FreeData)
+{
+ UINTN i;
+
+//-----------------------------------------
+ if (FreeData)for (i=0; i<Lst->ItemCount; i++)
+ {
+ if (Lst->Items[i])pBS->FreePool(Lst->Items[i]);
+ }
+
+ if (Lst->Items) pBS->FreePool(Lst->Items);
+
+ Lst->Items=NULL;
+ Lst->ItemCount=0;
+ Lst->InitialCount=0;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: CopyItemLst
+//
+// Description:
+// EFI_STATUS CopyItemLst(IN T_ITEM_LIST *Lst, OUT T_ITEM_LIST **NewLstPtr)
+// copies Lst into a new list and provides the address of the copy in
+// NewLstPtr.
+//
+// Input:
+// IN T_ITEM_LIST *Lst
+// List to be copied.
+//
+// OUT T_ITEM_LIST **NewLstPtr
+// Location to store the address of the new copy.
+//
+// Output:
+// EFI_OUT_OF_RESOURCES, if memory allocation fails.
+// Otherwise, EFI_SUCCESS.
+//
+// Modified:
+//
+// Referrals:
+// MallocZ
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_STATUS CopyItemLst(T_ITEM_LIST *Lst, T_ITEM_LIST **NewLstPtr)
+{
+ UINTN i = 0;
+ T_ITEM_LIST *NewLst = NULL;
+
+ *NewLstPtr = NULL;
+ *NewLstPtr = MallocZ(sizeof(T_ITEM_LIST));
+
+ if (!*NewLstPtr)
+ {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewLst = *NewLstPtr;
+ NewLst->InitialCount = Lst->InitialCount;
+ NewLst->ItemCount = Lst->ItemCount;
+
+ if (Lst->ItemCount == 0)
+ {
+ return EFI_SUCCESS;
+ }
+
+ NewLst->Items = MallocZ( Lst->ItemCount * sizeof(VOID*) );
+
+ if (!NewLst->Items)
+ {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (i = 0; i < Lst->ItemCount; i++)
+ {
+ NewLst->Items[i] = NULL;
+
+ if (Lst->Items[i])
+ {
+ NewLst->Items[i] = MallocZ( sizeof(Lst->Items[i]) );
+
+ if (!NewLst->Items[i])
+ {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ pBS->CopyMem(NewLst->Items[i], Lst->Items[i], sizeof(Lst->Items[i]));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: ValidateDescriptor
+//
+// Description:
+// BOOLEAN ValidateDescriptor(IN ASLR_QWORD_ASD *Descriptor,
+// IN ASLR_TYPE_ENUM ResType, IN BOOLEAN Fixed) validates a ASLV_LARGE_RES
+// descriptor.
+//
+// Input:
+// IN ASLR_QWORD_ASD *Descriptor
+// Descriptor to be validated.
+//
+// IN ASLR_TYPE_ENUM ResType
+// The resource type of the descriptor. Valid values are:
+// tResAll, tResIoMem, tResBus
+//
+// IN BOOLEAN Fixed
+// If TRUE, checks the general flags for consistancy.
+//
+// Output:
+// TRUE if a valid ASLR_QWORD_ASD descriptor. Otherwise, FALSE.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+// Helper function for ValidateDescriptorBlock.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+BOOLEAN ValidateDescriptor(ASLR_QWORD_ASD *Descriptor,ASLR_TYPE_ENUM ResType,BOOLEAN Fixed)
+{
+ //Check ASL Resource Descriptor Header consistancy
+ if (
+ (Descriptor->Hdr.Name!=ASLV_RT_QWORD_ASD) ||
+ (Descriptor->Hdr.Type!=ASLV_LARGE_RES) ||
+ (Descriptor->Hdr.Length!=sizeof(ASLR_QWORD_ASD)-sizeof(ASLRF_L_HDR) )
+ )return FALSE;
+
+ //Check ASL Resource Descriptor General Flags Consistancy
+ if (Fixed)
+ {
+ if (
+ (!Descriptor->GFlags._MIF) ||
+ (!Descriptor->GFlags._MAF)
+ )return FALSE;
+ }
+
+ if (Descriptor->Type>2) return FALSE;
+
+ //Check ASL Resource Descriptor Resource Type
+ switch (ResType)
+ {
+ case tResBus:
+
+ if (Descriptor->Type!=ASLRV_SPC_TYPE_BUS) return FALSE;
+
+ if ((Descriptor->_MIN+Descriptor->_LEN)>0x100)return FALSE;
+
+ break;
+ case tResIoMem:
+
+ if (Descriptor->Type>=ASLRV_SPC_TYPE_BUS) return FALSE;
+
+ break;
+ case tResAll:
+
+ if (Descriptor->Type>ASLRV_SPC_TYPE_BUS) return FALSE;
+
+ break;
+ default : return FALSE;
+ }
+
+ return TRUE;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: ValidateDescriptorBlock
+//
+// Description:
+// UINTN ValidateDescriptorBlock(IN ASLR_QWORD_ASD *DscStart,
+// IN ASLR_TYPE_ENUM ResType, IN BOOLEAN Fixed) validates the consistancy of
+// the provided ACPI QWORD resource descriptors block which contains some
+// number of ASLR_QWORD_ASDs in memory terminated by an ASLR_EndTag. Returns
+// the total size of the resource descriptors plus the size of the
+// ASLR_EndTag.
+//
+// Input:
+// IN ASLR_QWORD_ASD *DscStart
+// Pointer to the first descriptor in the block to be validated.
+//
+// IN ASLR_TYPE_ENUM ResType
+// The resource type of the descriptors. Valid values are:
+// tResAll, tResIoMem, tResBus
+//
+// IN BOOLEAN Fixed
+// If TRUE, checks the general flags for consistancy.
+//
+// Output:
+// UINTN size of the resource descriptor block plus the size of the
+// ASLR_EndTag.
+//
+// Modified:
+//
+// Referrals:
+// ValidateDescriptor
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+UINTN ValidateDescriptorBlock(ASLR_QWORD_ASD* DscStart, ASLR_TYPE_ENUM ResType, BOOLEAN Fixed)
+{
+ ASLR_QWORD_ASD *qwd=DscStart;
+ UINTN len=0;
+ ASLR_EndTag *endtag=(ASLR_EndTag*)DscStart;
+
+//-----------------------------------
+ //resource descriptor is empty...
+ if (endtag->Hdr.HDR==ASLV_END_TAG_HDR) return sizeof(ASLR_EndTag);
+
+ while (endtag->Hdr.HDR!=ASLV_END_TAG_HDR)
+ {
+ if (!ValidateDescriptor(qwd, ResType, Fixed)) return 0;
+ else len+=sizeof(ASLR_QWORD_ASD);
+
+ qwd++;
+ endtag=(ASLR_EndTag*)qwd;
+ }
+
+ len+=sizeof(ASLR_EndTag);
+ return len;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: CheckDsdt
+//
+// Description:
+// BOOLEAN CheckDsdt(IN ACPI_HDR *Dsdt) checks the signature of the provided
+// ACPI header for the DSDT signature.
+//
+// Input:
+// IN ACPI_HDR *Dsdt
+// Pointer to the ACPI header to be checked for the DSDT signature.
+//
+// Output:
+// TRUE if the header signature is that of the DSDT. Otherwise, FALSE.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+BOOLEAN CheckDsdt(ACPI_HDR *Dsdt)
+{
+ if (Dsdt->Signature!=DSDT_SIG) return FALSE;
+
+ return TRUE;
+}
+
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: GetRbAmlPackagePointer
+//
+// Description:
+// This function returns a pointer to a named AML Package object in the
+// specified root bridge scope along with information necessary to
+// dynamically read and/or modify its data.
+//
+// This function also serves as an example of how a named Package object
+// pointer can be obtained, if the scope path is known.
+//
+// Input:
+// IN ACPI_HDR **Dsdt
+// - This pointer is either NULL or the pointer to the DSDT.
+// (If it is NULL, LibGetDsdt is called to obtain the
+// pointer.)
+// IN CHAR8 *RbName
+// - This string specifies the name of the root bridge
+// device for which the Package object is to be found.
+// IN CHAR8 *PackageName
+// - This string specifies the name of the Package object
+// to be found.
+// OUT ASL_OBJ_INFO *Package
+// - This parameter is updated to contain the address of
+// the ASL_OBJ_INFO structure associated with the
+// located Package object.
+// OUT PACKAGE_ELEMENT *Elements
+// - This parameter is updated to contain the address
+// of the first element of the located Package object.
+// OUT UINT8 *ElementCount
+// - This parameter is updated to contain the number
+// of elements in the located Package object.
+//
+// Output:
+// EFI_STATUS (Return Value)
+// = EFI_SUCCESS if successful
+// = or valid EFI error code
+//
+// Modified:
+// None
+//
+// Referrals:
+// LibGetDsdt()
+// GetAslObj()
+//
+// Notes:
+// Package objects are aggregate arrays of elements that can be of
+// different size and type. This function assumes the caller
+// understands the structure of the package object associated with the
+// PackageName paramenter and can iterate through the elements.
+//
+// Prototypes for several element types are provided in AcpiRes.h
+// (see PACKAGE_ELEMENT). Additional types can be supported by
+// typecasting PACKAGE_ELEMENT.Ptr.
+//
+// Example: Supported ASL Package Declarations (must be initialized)
+//
+// Scope(\_SB.PCI0) {
+// Name (PAK1, Package ()
+// {
+// 0x0123,
+// 0x0123,
+// 0x0123,
+// 0x0123,
+// })
+// }
+//
+// Scope(\_SB.PCI1) {
+// Name (PAK1, Package ()
+// {
+// 0x0123,
+// 0x0123,
+// 0x0123,
+// 0x0123,
+// })
+// }
+//
+// Example: Usage
+//
+// VOID Function(){
+// ASL_OBJ_INFO Package;
+// PACKAGE_ELEMENT Element;
+// UINT8 ElementCount;
+//
+// Status = GetRbAmlPackagePointer( "PCI1", "PAK1",
+// &Package, &Element, &ElementCount);
+// ...
+// }
+//
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS GetRbAmlPackagePointer(
+ IN ACPI_HDR **Dsdt,
+ IN CHAR8 *RbName,
+ IN CHAR8 *PackageName,
+ OUT ASL_OBJ_INFO *Package,
+ OUT PACKAGE_ELEMENT *Elements,
+ OUT UINT8 *ElementCount )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Address;
+ ASL_OBJ_INFO RbScope;
+ AML_PACKAGE_HEADER *Pkg;
+
+ if (*Dsdt == NULL){
+ Status = LibGetDsdt(&Address, EFI_ACPI_TABLE_VERSION_ALL);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ else {
+ *Dsdt = (ACPI_HDR*)Address;
+ }
+ }
+
+ // Get a pointer to this root bridge's device scope
+
+ Status = GetAslObj( (UINT8*)(*Dsdt + 1),
+ (*Dsdt)->Length - sizeof(ACPI_HDR) - 1,
+ RbName,
+ otDevice,
+ &RbScope );
+
+ // Get a pointer to the AML Package object
+
+ if (!EFI_ERROR(Status)){
+ Status = GetAslObj( (UINT8*)RbScope.DataStart,
+ RbScope.Length,
+ PackageName,
+ otName,
+ Package );
+ }
+
+ // Parse the Package object to get a pointer to the first element and
+ // number of elements.
+
+ if (!EFI_ERROR(Status)){
+ Pkg = Package->DataStart;
+
+ // Check ByteCount to determine the encoding and obtain a pointer
+ // to the first element and the element count.
+
+ switch (Pkg->Encoding.Small.ByteCount) {
+ case 0:
+ (*Elements).Ptr = &Pkg->Encoding.Small.Element;
+ *ElementCount = Pkg->Encoding.Small.ElementCount;
+ break;
+ case 1:
+ (*Elements).Ptr = &Pkg->Encoding.Large1.Element;
+ *ElementCount = Pkg->Encoding.Large1.ElementCount;
+ break;
+ case 2:
+ (*Elements).Ptr = &Pkg->Encoding.Large2.Element;
+ *ElementCount = Pkg->Encoding.Large2.ElementCount;
+ break;
+ case 3:
+ (*Elements).Ptr = &Pkg->Encoding.Large3.Element;
+ *ElementCount = Pkg->Encoding.Large3.ElementCount;
+ }
+ }
+
+ return Status;
+}
+
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: GetPackageLen
+//
+// Description:
+// UINTN GetPackageLen(IN AML_PACKAGE_LBYTE *Pck, OUT UINT8 *BytesCnt)
+// determines the length in bytes of an AML package.
+//
+// Input:
+// IN AML_PACKAGE_LBYTE *Pck
+// AML package to be measured.
+//
+// OUT UINT8 *BytesCnt
+// The ByteCount value of the package.
+//
+// Output:
+// UINTN size of the AML package in bytes.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+//will determine length in bytes of a package
+UINTN GetPackageLen(AML_PACKAGE_LBYTE *Pck, UINT8 *BytesCnt)
+{
+ UINTN len=0;
+ UINT8 *p=(UINT8*)Pck;
+
+//------------------
+ if (BytesCnt)*BytesCnt=0;
+
+ if (!Pck->ByteCount) len=Pck->Length;
+ else
+ {
+ len|=(Pck->Length&0x0F);
+
+ if (BytesCnt)*BytesCnt=Pck->ByteCount;
+
+ switch (Pck->ByteCount)
+ {
+ case 1:
+ {
+ UINT8 b=*(p+1);
+ len|=(b<<4);
+ } break;
+ case 2:
+ {
+ UINT16 w=(UINT16)(*((UINT16*)(p+1)));
+ len|=(w<<4);
+ } break;
+ case 3:
+ {
+ UINT32 d=(UINT32)(*((UINT32*)(p+1)));
+ d&=0xffffff;
+ len|=(d<<4);
+ } break;
+ } //switch
+ }
+
+ return len;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: ConvertAslName
+//
+// Description:
+// UINT32 ConvertAslName(IN UINT8 *AslName) converts an ASL name into a
+// UINT32 value and returns it.
+//
+// Input:
+// IN UINT8 *AslName
+// Pointer to the ASL name string.
+//
+// Output:
+// UINT32 translation of the ASL name.
+//
+// Modified:
+//
+// Referrals:
+// Strlen
+// MemCpy
+//
+// Notes:
+// Helper function for FindAslObjectName.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+UINT32 ConvertAslName(UINT8 *AslName)
+{
+ AML_NAME_SEG n;
+ UINTN l=Strlen(AslName);
+//-------------------------
+ n.NAME=0x5F5F5F5F;
+ MemCpy(&n.Name[0],AslName,l);
+ return n.NAME;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: FindAslObjectName
+//
+// Description:
+// VOID* FindAslObjectName(IN UINT8 *Start, IN UINT8 *ObjName, IN UINTN Len)
+// finds an ASL object by its name string and returns its location.
+//
+// Input:
+// IN UINT8 *Start
+// Location to begin scanning for the ASL object.
+//
+// IN UINT8 *ObjName
+// Name of the ASL object to be located.
+//
+// IN UINTN Len
+// Maximum length of bytes to scan for the ASL object.
+//
+// Output:
+// VOID* pointer to the start of the ASL name string in memory.
+//
+// Modified:
+//
+// Referrals:
+// ConvertAslName
+//
+// Notes:
+// Helper function for GetAslObj.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID* FindAslObjectName(UINT8 *Start, UINT8 *ObjName, UINTN Len)
+{
+ unsigned int i;
+ UINT8 *p;
+ AML_NAME_SEG *obj,nm;
+//------------------------------
+ nm.NAME=ConvertAslName(ObjName);
+
+ p=Start;
+
+ for (i=0; i<Len; i++)
+ {
+ obj=(AML_NAME_SEG*)(&p[i]);
+
+ if (obj->NAME!=nm.NAME)continue;
+
+ return &p[i];
+ }
+
+ return NULL;
+}
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: HideAslMethodFromOs
+//
+// Description:
+// Destroys Method passed as MethodName parameter if it is present in ASL object
+// described by AslObj parameter
+//
+// Input:
+// IN ASL_OBJ_INFO *AslObj
+// Pointer to ASL_OBJ_INFO structure, which discribes ASL object to modify
+//
+// UINT8 *MethodName
+// Name of the ASL Method to be destroyed.
+//
+//
+// Referrals:
+// ConvertAslName
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID HideAslMethodFromOs (ASL_OBJ_INFO *AslObj, UINT8 *MethodName)
+{
+ UINT32 AslMethodName = ConvertAslName(MethodName), i, Position; //*(UINT32*)MethodName
+ UINT8 *Start = AslObj->DataStart;
+
+// TRACE ((-1,"AslMethodNameHex = %X, Str=%s; Start= %lX\n", AslMethodName, MethodName, (UINT64) Start));
+
+ for (i = 0; i < AslObj->Length; i++)
+ {
+ Position =*(UINT32*)(Start+i);
+
+ if (Position == AslMethodName)
+ // If method is found
+ {
+// TRACE ((-1,"METHOD FOUND = %x,\n", Position));
+ Start[i] = 'X'; //Replace leading _ with X
+ return;
+ }
+ }
+
+}
+
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: CheckOpCode
+//
+// Description:
+// BOOLEAN CheckOpCode(IN UINT8 *NameStart, IN UINT8 OpCode,
+// IN UINT8 ExtOpCode, OUT ASL_OBJ_INFO *ObjInfo) checks an ASL object for
+// the user provided op code and extended op code and returns the op code
+// location in a user allocated ASL_OBJ_INFO structure.
+//
+// Input:
+// IN UINT8 *NameStart
+// Pointer to the start of the ASL object's name.
+//
+// IN UINT8 OpCode
+// Op code to be checked.
+//
+// IN UINT8 ExtOpCode
+// Extended op code to be checked. If set as 0, only checks for OpCode.
+//
+// OUT ASL_OBJ_INFO *ObjInfo
+// Pointer to a user allocated ASL_OBJ_INFO structure which will be updated
+// with the associated information if the op codes are located. If an
+// extended op code is specified, ObjInfo->Object is filled with the location
+// of the extended op code; otherwise ObjInfo->Object refers to the location
+// of the op code.
+//
+// Output:
+// TRUE if the op code and extended op code (if specified) are located;
+// otherwise, FALSE.
+//
+// Modified:
+//
+// Referrals:
+// GetPackageLen
+//
+// Notes:
+// Helper function for GetAslObj.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+BOOLEAN CheckOpCode(UINT8 *NameStart, UINT8 OpCode, UINT8 ExtOpCode, ASL_OBJ_INFO *ObjInfo)
+{
+ UINT8 *p, *p1;
+ INTN i;
+
+//---------------------
+ //Maximum number of bytes in PackageLength is 4
+ if ( (*(NameStart-1))==AML_PR_ROOT || (*(NameStart-1))==AML_PR_PARENT) NameStart--;
+
+ //if we Looking For ASL Name Object its a special case.
+ if (OpCode==AML_OP_NAME && !ExtOpCode)
+ {
+ p=NameStart-1;
+
+ if (*p==OpCode)
+ {
+ ObjInfo->Object=p;
+ ObjInfo->ObjName=NameStart;
+ ObjInfo->Length=0;
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ //if we Looking For ASL Name Object its a special case.
+ if (OpCode==AML_OP_OPREG && ExtOpCode)
+ {
+ p=NameStart-2;
+
+ if (*p==ExtOpCode && *(p+1)==OpCode)
+ {
+ ObjInfo->Object=p;
+ ObjInfo->ObjName=NameStart;
+ ObjInfo->Length=0;
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ for (i=2; i<6; i++)
+ {
+ p=NameStart-i;
+
+ if (ExtOpCode) p1=p-1;
+ else p1=NULL;
+
+ if (p1)if (*p1!=ExtOpCode) continue;
+
+ if (*p!=OpCode) continue;
+
+ if (p1)ObjInfo->Object=p1;
+ else ObjInfo->Object=p;
+
+ ObjInfo->Length=GetPackageLen((AML_PACKAGE_LBYTE*)(p+1),NULL);
+ ObjInfo->ObjName=NameStart;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: GetAslObj
+//
+// Description:
+// EFI_STATUS GetAslObj(IN UINT8 *Start, IN UINTN Length, IN UINT8 *Name,
+// IN ASL_OBJ_TYPE ObjType, OUT ASL_OBJ_INFO *ObjInfo)
+//
+// Input:
+// IN UINT8 *Start
+// Starting location in memory to begin scanning for the desired ASL object.
+//
+// IN UINTN Length
+// Maximum number of bytes in memory to be scanned starting from Start for
+// the ASL object.
+//
+// IN UINT8 *Name
+// Pointer to the name of the ASL object to be located.
+//
+// IN ASL_OBJ_TYPE ObjType
+// Type of the ASL object to be located. Supports: otScope, otName, otProc,
+// otTermal, otDevice, otMethod, otPwrRes, otOpReg
+//
+// OUT ASL_OBJ_INFO *ObjInfo
+// Returns completed ASL_OBJ_INFO structure, if the ASL object is found.
+//
+// Output:
+// EFI_NOT_FOUND, if object not found or invalid type.
+// Otherwise, EFI_SUCCESS.
+//
+// Modified:
+//
+// Referrals:
+// FindAslObjectName
+// CheckOpCode
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+//Since the search is done by locating the OBJECT name.
+//Caller must know what ASL Object Type he is looking for.
+EFI_STATUS GetAslObj(UINT8 *Start, UINTN Length, UINT8 *Name, ASL_OBJ_TYPE ObjType, ASL_OBJ_INFO *ObjInfo)
+{
+ UINT8 *pn, *s, eop,op;
+ UINTN l, i;
+ BOOLEAN objfound=FALSE;
+// ASL_OBJ_INFO objinf;
+//---------------------------
+ //if(!CheckDsdt(PDsdt)) return FALSE;
+
+ //s=((UINT8*)PDsdt)+sizeof(ACPI_HDR);
+ s=Start;
+ //l=PDsdt->Length-sizeof(ACPI_HDR)-1;
+ l=Length;
+
+ while (!objfound)
+ {
+
+ pn=FindAslObjectName(s,Name,l);
+
+ if (!pn) return EFI_NOT_FOUND;
+
+ //If we found the name let's check if it is the Object we are looking for
+ //it could be just object referance, or field definition inside the object,
+ //or double name, or multiple name definition we must filter such situations
+ // and make sure we have got the actual object but not its reference instance
+ switch (ObjType)
+ {
+ case otScope :
+ i=0;
+ eop=0;
+ op=AML_OP_SCOPE;
+ break;
+ case otName :
+ i=0;
+ eop=0;
+ op=AML_OP_NAME;
+ break;
+ case otProc :
+ i=6;
+ eop=AML_PR_EXTOP;
+ op=AML_OP_PROC;
+ break;
+ case otTermal :
+ i=0;
+ eop=AML_PR_EXTOP;
+ op=AML_OP_THERMAL;
+ break;
+ case otDevice :
+ i=0;
+ eop=AML_PR_EXTOP;
+ op=AML_OP_DEVICE;
+ break;
+ case otMethod :
+ i=1;
+ eop=0;
+ op=AML_OP_METHOD;
+ break;
+ case otPwrRes :
+ i=3;
+ eop=AML_PR_EXTOP;
+ op=AML_OP_PWRRES;
+ break;
+ case otOpReg :
+ i=0;
+ eop=AML_PR_EXTOP;
+ op=AML_OP_OPREG;
+ break;
+
+ default: return EFI_NOT_FOUND;
+ } //switch
+
+ objfound=CheckOpCode(pn, op, eop, ObjInfo);
+
+ if (!objfound)
+ {
+ l-=(UINTN)(pn-s)-4;
+ s=pn+4;
+ continue;
+ }
+
+ ObjInfo->ObjType=ObjType;
+ ObjInfo->DataStart=pn+i+4;
+
+ return EFI_SUCCESS;
+ } //while ()
+
+ return EFI_NOT_FOUND;
+}
+
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: UpdateAslNameBuffer
+//
+// Description:
+// EFI_STATUS UpdateAslNameBuffer(UINT8 *BufferStart, UINTN BufferLen,
+// IN UINT8 *ObjName, IN UINT64 Value) locates an ASL object by its name,
+// ObjName, in Memory Buffer specified by BufferStart, and BufferLen
+// and updates its data start with the user provided Value.
+//
+// Input:
+// IN UINT8 *BufferStart
+// Pointer to the DSDT.
+//
+// UINTN BufferLen
+// Length of the Buffer
+//
+// IN UINT8 *ObjName
+// Name of the ASL object to be updated.
+//
+// IN UINT64 Value
+// New value for the ASL object's data entry.
+//
+// Output:
+// EFI_INVALID_PARAMETER, if the DSDT pointer, ObjName or Value are invalid.
+// EFI_NOT_FOUND, if object specified by ObjName not present.
+// Otherwise, EFI_SUCCESS.
+//
+// Modified:
+//
+// Referrals:
+// GetAslObj
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_STATUS UpdateAslNameBuffer(UINT8 *BufferStart, UINTN BufferLen, UINT8 *ObjName, UINT64 Value)
+{
+ EFI_STATUS Status;
+ ASL_OBJ_INFO obj;
+//---------------
+ Status=GetAslObj(BufferStart,BufferLen, ObjName, otName, &obj);
+
+ if EFI_ERROR(Status) return Status;
+
+ switch (*((UINT8*)obj.DataStart))
+ {
+ case AML_PR_BYTE:
+ {
+ UINT8 *p = (UINT8*)((UINT8*)obj.DataStart+1);
+ //----------------------------------
+ *p=(UINT8)Value;
+ } break;
+
+ case AML_PR_WORD:
+ {
+ UINT16 *p = (UINT16*)((UINT8*)obj.DataStart+1);
+ //----------------------------------
+ *p=(UINT16)Value;
+ } break;
+
+ case AML_PR_DWORD:
+ {
+ UINT32 *p = (UINT32*)((UINT8*)obj.DataStart+1);
+ //----------------------------------
+ *p=(UINT32)Value;
+ } break;
+
+ case AML_PR_QWORD:
+ {
+ UINT64 *p = (UINT64*)((UINT8*)obj.DataStart+1);
+ //----------------------------------
+ *p=(UINT64)Value;
+ } break;
+
+ case AML_ZERO_OP: case AML_ONE_OP:
+ {
+ if ((Value == 0) || (Value == 1))
+ {
+ UINT8 *p = (UINT8*)((UINT8*)obj.DataStart);
+ *p = (UINT8)Value;
+ }
+
+ else
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+ } break;
+ default:
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: UpdateAslNameOfDevice
+//
+// Description:
+// EFI_STATUS UpdateAslNameOfDevice(IN ACPI_HDR *PDsdt, IN CHAR8 *DeviceName,
+// CHAR8 *ObjName, IN UINT64 Value) locates an ASL Device Object by its name,
+// DeviceName, and then In the scope of this Device Object, trys to locate a
+// Name Object, ObjName, in the DSDT. If found it updates its data place holder
+// with user provided Value.
+//
+// Input:
+// IN ACPI_HDR *PDsdt
+// Pointer to the DSDT.
+//
+// IN CHAR8 *DeviceName
+// Name of the ASL Device object having in it's scope Name Object to be updated.
+//
+// IN CHAR8 *ObjName
+// Name of the ASL Name Object to be updated.
+//
+// IN UINT64 Value
+// New value for the ASL object's data entry.
+//
+// Output:
+// EFI_INVALID_PARAMETER, if the DSDT pointer, ObjName or Value are invalid.
+// EFI_NOT_FOUND, if object specified by Device Name Or ObjName not present.
+// Otherwise, EFI_SUCCESS.
+//
+// Modified:
+//
+// Referrals:
+// CheckDsdt
+// GetAslObj
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_STATUS UpdateAslNameOfDevice(ACPI_HDR *PDsdt, CHAR8 *DeviceName, CHAR8 *ObjName, UINT64 Value)
+{
+ EFI_STATUS Status;
+ ASL_OBJ_INFO obj;
+
+//---------------
+ if (!CheckDsdt(PDsdt)) return EFI_INVALID_PARAMETER;
+
+ Status=GetAslObj((UINT8*)(PDsdt+1),PDsdt->Length-sizeof(ACPI_HDR)-1, DeviceName, otDevice, &obj);
+
+ if EFI_ERROR(Status) return Status;
+
+ Status=UpdateAslNameBuffer((UINT8*)obj.DataStart, obj.Length, ObjName, Value);
+ return Status;
+}
+
+
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: UpdateAslNameObject
+//
+// Description:
+// EFI_STATUS UpdateAslNameObject(IN ACPI_HDR *PDsdt, IN UINT8 *ObjName,
+// IN UINT64 Value) locates an ASL object by its name, ObjName, in the DSDT
+// and updates its data start with the user provided Value.
+//
+// Input:
+// IN ACPI_HDR *PDsdt
+// Pointer to the DSDT.
+//
+// IN UINT8 *ObjName
+// Name of the ASL object to be updated.
+//
+// IN UINT64 Value
+// New value for the ASL object's data entry.
+//
+// Output:
+// EFI_INVALID_PARAMETER, if the DSDT pointer, ObjName or Value are invalid.
+// Otherwise, EFI_SUCCESS.
+//
+// Modified:
+//
+// Referrals:
+// CheckDsdt
+// GetAslObj
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_STATUS UpdateAslNameObject(ACPI_HDR *PDsdt, UINT8 *ObjName, UINT64 Value)
+{
+//------------------------------------
+ if (!CheckDsdt(PDsdt)) return EFI_INVALID_PARAMETER;
+
+ return UpdateAslNameBuffer((UINT8*)(PDsdt+1),PDsdt->Length-sizeof(ACPI_HDR)-1, ObjName, Value);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: ChsumTbl
+//
+// Description:
+// UINT8 ChsumTbl(IN UINT8 *TblStart, IN UINT32 BytesCount) calculates the
+// checksum of a table starting at TblStart of length BytesCount and returns
+// the checksum value.
+//
+// Input:
+// IN UINT8 *TblStart
+// Starting address of the memory area to checksum.
+//
+// IN UINT32 BytesCount
+// Length in bytes of the memory area to checksum.
+//
+// Output:
+// UINT8 checksum value starting from TblStart and ending at
+// TblStart + BytesCount.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+UINT8 ChsumTbl(UINT8* TblStart, UINT32 BytesCount)
+{
+ UINTN i;
+ UINT8 res=*TblStart;
+
+ for (i=1; i<BytesCount; i++) res+=TblStart[i];
+
+ res=0-res;
+ return(res);
+} //checksum_table
+
+static EFI_GUID gAmiIsaDmaIrqMaskVarGuid = AMI_IRQ_DMA_MASK_VARIABLE_GUID;
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: AmiIsaIrqMask
+//
+// Description:
+// EFI_STATUS AmiIsaIrqMask(IN OUT UINT16 *IsaIrqMask, IN BOOLEAN Get) sets
+// or retrieves the ISA IRQ mask from NVRAM depending upon the Get input.
+//
+// Input:
+// IN OUT UINT16 *IsaIrqMask
+// If Get is TRUE, returns an address to the ISA IRQ mask. If Get is FALSE,
+// used to update the ISA IRQ mask NVRAM variable. User is responsible for
+// allocating and managing this memory.
+//
+// IN BOOLEAN Get
+// If TRUE, causes function to return an address to the ISA IRQ mask.
+// If FALSE, causes function to use the user provided ISA IRQ mask to update
+// the NVRAM variable with its value.
+//
+// Output:
+// EFI_NOT_FOUND, if the ISA IRQ mask NVRAM variable is not found.
+// EFI_DEVICE_ERROR, if the ISA IRQ mask NVRAM variable could not be
+// accessed due to a hardware error.
+// EFI_SECURITY_VIOLATION, if the ISA IRQ mask NVRAM variable could be not
+// be accessed due to a authentication failure.
+// Otherwise, EFI_SUCCESS.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_STATUS AmiIsaIrqMask(UINT16 *IsaIrqMask, BOOLEAN Get)
+{
+ UINTN sz=sizeof(UINT16);
+ EFI_STATUS Status;
+//-----------------------
+
+ if (Get) Status = pRS->GetVariable(L"IsaIrqMask", &gAmiIsaDmaIrqMaskVarGuid, NULL, &sz, IsaIrqMask);
+ else Status=pRS->SetVariable(L"IsaIrqMask",&gAmiIsaDmaIrqMaskVarGuid,EFI_VARIABLE_BOOTSERVICE_ACCESS, sz, IsaIrqMask);
+
+ return Status;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: AmiIsaDmaMask
+//
+// Description:
+// EFI_STATUS AmiIsaDmaMask(IN OUT UINT8 *IsaDmaMask, IN BOOLEAN Get) sets
+// or retrieves the ISA DMA mask from NVRAM depending upon the Get input.
+//
+// Input:
+// IN OUT UINT8 *IsaDmaMask
+// If Get is TRUE, returns an address to the ISA DMA mask. If Get is FALSE,
+// used to update the ISA DMA mask NVRAM variable. User is responsible for
+// allocating and managing this memory.
+//
+// IN BOOLEAN Get
+// If TRUE, causes function to return an address to the ISA DMA mask.
+// If FALSE, causes function to use the user provided ISA DMA mask to update
+// the NVRAM variable with its value.
+//
+// Output:
+// EFI_NOT_FOUND, if the ISA DMA mask NVRAM variable is not found.
+// EFI_DEVICE_ERROR, if the ISA DMA mask NVRAM variable could not be
+// accessed due to a hardware error.
+// EFI_SECURITY_VIOLATION, if the ISA DMA mask NVRAM variable could be not
+// be accessed due to a authentication failure.
+// Otherwise, EFI_SUCCESS.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_STATUS AmiIsaDmaMask(UINT8 *IsaDmaMask, BOOLEAN Get)
+{
+ UINTN sz=sizeof(UINT8);
+ EFI_STATUS Status;
+//-----------------------
+
+ if (Get) Status = pRS->GetVariable(L"IsaDmaMask", &gAmiIsaDmaIrqMaskVarGuid, NULL, &sz, IsaDmaMask);
+ else Status=pRS->SetVariable(L"IsaDmaMask",&gAmiIsaDmaIrqMaskVarGuid,EFI_VARIABLE_BOOTSERVICE_ACCESS, sz, IsaDmaMask);
+
+ return Status;
+}
+
+static EFI_GUID gAmiPciOutOfResVarGuid = AMI_PCI_OUT_OF_RESOURCES_GUID;
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: AmiPciOutOfRes
+//
+// Description:
+// EFI_STATUS AmiPciOutOfRes(AMI_OUT_OF_RES_VAR *AmiOutOfResData, IN BOOLEAN Get) sets
+// or retrieves the AMI_OUT_OF_RES_DATA from NVRAM depending upon the Get input.
+//
+// Input:
+// AMI_OUT_OF_RES_VAR *AmiOutOfResData
+// If Get is TRUE, returns an address to the AMI_OUT_OF_RES_VAR. If Get is FALSE,
+// used to update the AMI_OUT_OF_RES_VAR data NVRAM variable. User is responsible for
+// allocating and managing this memory.
+//
+// IN BOOLEAN Get
+// If TRUE, causes function to return an address to the ISA DMA mask.
+// If FALSE, causes function to use the user provided ISA DMA mask to update
+// the NVRAM variable with its value.
+//
+// Output:
+// EFI_NOT_FOUND, if the NVRAM variable is not found.
+// EFI_DEVICE_ERROR, if the NVRAM variable could not be
+// accessed due to a hardware error.
+// EFI_SECURITY_VIOLATION, if the NVRAM variable could be not
+// be accessed due to a authentication failure.
+// Otherwise, EFI_SUCCESS.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_STATUS AmiPciOutOfRes(AMI_OUT_OF_RES_VAR *AmiOutOfResData, BOOLEAN Get)
+{
+ AMI_OUT_OF_RES_VAR orv;
+ UINTN sz=sizeof(AMI_OUT_OF_RES_VAR);
+ EFI_STATUS Status;
+//-----------------------
+ if(!Get && AmiOutOfResData==NULL) return EFI_INVALID_PARAMETER;
+
+ if (Get) Status = pRS->GetVariable(L"AmiOutOfRes", &gAmiPciOutOfResVarGuid, NULL, &sz, &orv);
+ else Status=pRS->SetVariable(L"AmiOutOfRes",&gAmiPciOutOfResVarGuid,EFI_VARIABLE_BOOTSERVICE_ACCESS, sz, AmiOutOfResData);
+
+ if(Get && AmiOutOfResData!=NULL) *AmiOutOfResData=orv;
+
+ return Status;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: LibGetDsdt
+//
+// Description:
+// EFI_STATUS LibGetDsdt(OUT EFI_PHYSICAL_ADDRESS *DsdtAddr,
+// IN EFI_ACPI_TABLE_VERSION Version) retrieves a pointer to the DSDT ACPI
+// table for the user requested Version of ACPI.
+//
+// Input:
+// OUT EFI_PHYSICAL_ADDRESS *DsdtAddr
+// Address of the DSDT associated with the user provided Version.
+//
+// IN EFI_ACPI_TABLE_VERSION Version
+// Which version of ACPI's DSDT to return. Valid values include:
+// EFI_ACPI_TABLE_VERSION_1_0B, EFI_ACPI_TABLE_VERSION_X,
+// EFI_ACPI_TABLE_VERSION_NONE
+//
+// Output:
+// EFI_NOT_AVAILABLE_YET, if ACPI support protocol not installed yet.
+// Otherwise, EFI_SUCCESS.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_STATUS LibGetDsdt(EFI_PHYSICAL_ADDRESS *DsdtAddr, EFI_ACPI_TABLE_VERSION Version)
+{
+ static EFI_PHYSICAL_ADDRESS Dsdt1 = 0;
+ static EFI_PHYSICAL_ADDRESS Dsdt2 = 0;
+#if PI_SPECIFICATION_VERSION < 0x10014
+ ACPI_HDR *tbl = NULL;
+ EFI_ACPI_SUPPORT_PROTOCOL *as;
+#else
+ EFI_ACPI_SDT_HEADER *tbl = NULL;
+ EFI_ACPI_SDT_PROTOCOL *as;
+#endif
+
+ EFI_STATUS Status = EFI_NOT_FOUND;
+ UINTN i;
+ EFI_ACPI_TABLE_VERSION ver;
+ UINTN AcpiHandle;
+
+//---------------------------
+ if (!(Dsdt1 && Dsdt2)) {
+#if PI_SPECIFICATION_VERSION < 0x10014
+ Status=pBS->LocateProtocol(&gEfiAcpiSupportGuid, NULL, &as);
+#else
+ Status=pBS->LocateProtocol(&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
--- /dev/null
+++ b/Library/AmiBufferValidationLib.chm
Binary files 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 @@
+<component>
+ name = "AmiBufferValidationLib"
+ category = eModule
+ LocalRoot = "Library"
+ RefName = "AmiBufferValidationLib"
+[files]
+"AmiBufferValidationLib.sdl"
+"AmiBufferValidationLib.mak"
+"AmiBufferValidationLib.chm"
+"SmmAmiBufferValidationLib.c"
+[parts]
+"AmiBufferValidationLibInclude"
+<endComponent>
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
+#
+#**********************************************************************
+
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: AmiBufferValidationLib.mak
+#
+# Description:
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+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 @@
+<component>
+ name = "AmiDxeLib"
+ category = ModulePart
+ LocalRoot = "Library\"
+ RefName = "AmiDxeLib"
+[files]
+"\AmiDxeLib.sdl"
+"\AmiDxeLib.mak"
+"\EfiDBE.c"
+"\EfiLib.c"
+"\AcpiRes.c"
+"\Print.c"
+<endComponent>
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
+#
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: AmiDxeLib.mak
+#
+# Description:
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+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
--- /dev/null
+++ b/Library/AmiLib.chm
Binary files 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 @@
+<component>
+ 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"
+<endComponent>
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 @@
+<component>
+ name = "AmiPeiLib"
+ category = ModulePart
+ LocalRoot = "Library\"
+ RefName = "AmiPeiLib"
+[files]
+"\AmiPeiLib.sdl"
+"\AmiPeiLib.mak"
+"\PeiLib.c"
+<endComponent>
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
+#
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: AmiPeiLib.mak
+#
+# Description:
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+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
+//
+//*************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Debug.c
+//
+// Description:
+// Contains generic debug library functions.
+//
+//<AMI_FHDR_END>
+//*************************************************************************
+#include <AmiLib.h>
+#include <StatusCodes.h>
+
+//*************************************************************************
+//<AMI_GHDR_START>
+//
+// 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.
+//
+//<AMI_GHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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));
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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));
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//
+// 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
+//
+//
+//*************************************************************************
+//<AMI_FHDR_START>
+//
+// 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.
+//
+//<AMI_FHDR_END>
+//*************************************************************************
+#include <EFI.h>
+
+#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
+
+
+//*************************************************************************
+//<INT:AMI_SHDR_START>
+//
+// 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:
+//
+//<INT:AMI_SHDR_END>
+//*************************************************************************
+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;
+
+//*************************************************************************
+//<INT:AMI_PHDR_START>
+//
+// 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:
+//
+//<INT:AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<INT:AMI_PHDR_START>
+//
+// 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:
+//
+//<INT:AMI_PHDR_END>
+//*************************************************************************
+STATIC
+UINT32
+GetBits(
+ IN SCRATCH_DATA *Sd,
+ IN UINT16 NumOfBits
+ )
+{
+ UINT32 OutBits;
+
+ OutBits = (UINT32)(Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));
+
+ FillBuf (Sd, NumOfBits);
+
+ return OutBits;
+}
+
+//*************************************************************************
+//<INT:AMI_PHDR_START>
+//
+// 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:
+//
+//<INT:AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<INT:AMI_PHDR_START>
+//
+// 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:
+//
+//<INT:AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<INT:AMI_PHDR_START>
+//
+// 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:
+//
+//<INT:AMI_PHDR_END>
+//*************************************************************************
+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) );
+}
+
+//*************************************************************************
+//<INT:AMI_PHDR_START>
+//
+// 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:
+//
+//<INT:AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<INT:AMI_PHDR_START>
+//
+// 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:
+//
+//<INT:AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<INT:AMI_PHDR_START>
+//
+// 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:
+//
+//<INT:AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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
+//
+//*************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: EfiDBE.c
+//
+// Description:
+// EFI Generic Database Engine serves all data storage, search and
+// maintanance needs for Database Engine (DBE) objects.
+//
+//<AMI_FHDR_END>
+//*************************************************************************
+#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>
+//*************************************************************************
+
+//*************************************************************************
+//<INT:AMI_PHDR_START>
+//
+// 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:
+//
+//<INT:AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<INT:AMI_PHDR_START>
+//
+// 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:
+//
+//<INT:AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<INT:AMI_PHDR_START>
+//
+// 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:
+//
+//<INT:AMI_PHDR_END>
+//*************************************************************************
+INTN AddrRRCmp(
+ IN VOID* *pContext, VOID *pRecord1, VOID *pRecord2
+)
+{
+ return (UINTN)pRecord1-(UINTN)pRecord2;
+}
+
+//*************************************************************************
+//<INT:AMI_PHDR_START>
+//
+// 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:
+//
+//<INT:AMI_PHDR_END>
+//*************************************************************************
+INTN AddrKRCmp(
+ IN DBE_OFFSET_KEY_CONTEXT *pContext, VOID *pKey, VOID *pRecord
+)
+{
+ return (UINTN)*(UINTN*)pKey-(UINTN)pRecord;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+
+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;
+}
+
+//*************************************************************************
+//<INT:AMI_PHDR_START>
+//
+// 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.
+//
+//<INT:AMI_PHDR_END>
+//*************************************************************************
+#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;i<Database->KeyCount;i++){
+ for(j=0;j<Database->RecordCount-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
+
+//*************************************************************************
+//<INT:AMI_PHDR_START>
+//
+// 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:
+//
+//<INT:AMI_PHDR_END>
+//*************************************************************************
+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; i<Database->KeyCount; 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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;i<Database->KeyCount;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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<INT:AMI_PHDR_START>
+//
+// 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:
+//
+//<INT:AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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.
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: EfiLib.c
+//
+// Description:
+// Contains generic EFI library functions.
+//
+//<AMI_FHDR_END>
+//*************************************************************************
+#include <AmiDxeLib.h>
+#include <StatusCodes.h>
+#include <Hob.h>
+#include <Token.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/LoadFile.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/ComponentName.h>
+#include <Protocol/StatusCode.h>
+#include <Protocol/DiskIo.h>
+#if SMM_SUPPORT
+#include <Protocol/SmmStatusCode.h>
+#endif
+#include <Protocol/Performance.h>
+#include <Protocol/Cpu.h>
+#include <ACPI50.h>
+
+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;
+
+//*************************************************************************
+//<AMI_GHDR_START>
+//
+// 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.
+//
+//<AMI_GHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_GHDR_START>
+//
+// 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.
+//
+//<AMI_GHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_GHDR_START>
+//
+// 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;
+//
+//<AMI_GHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID InitAmiLib(
+ IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ if (pST) return;
+ pST = SystemTable;
+ pBS = pST->BootServices;
+ pRS = pST->RuntimeServices;
+ TheImageHandle = ImageHandle;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+
+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
+ );
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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 && i<Count; i++)
+ {
+ UINTN j, InfoCount;
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *pInfo;
+ // This "if (!guidcmp(..." statement below is 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.
+ if (!guidcmp(ppGuid[i],&gEfiDiskIoProtocolGuid)) continue;
+ if (EFI_ERROR(pBS->OpenProtocolInformation(
+ Controller,ppGuid[i],&pInfo,&InfoCount
+ ))) continue;
+ for(j=0; j<InfoCount; j++)
+ {
+ EFI_COMPONENT_NAME_PROTOCOL *pComponentName;
+ if (pInfo[j].Attributes!=Attributes) continue;
+ if (Child){
+ if (pInfo[j].ControllerHandle!=Child)
+ continue;
+ if (ChildFound) *ChildFound=TRUE;
+ }
+ if (!EFI_ERROR(pBS->HandleProtocol(
+ 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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+void* Malloc(UINTN Size){
+ VOID *p=NULL;
+ pBS->AllocatePool(EfiBootServicesData,Size,&p);
+ return p;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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}
+};
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+//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);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_DEVICE_PATH_PROTOCOL* DPGetEndNode(EFI_DEVICE_PATH_PROTOCOL *pDp)
+{
+ if(!pDp)return NULL;
+ for( ; !isEndNode(pDp); pDp=NEXT_NODE(pDp)) ;
+ return pDp;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID* DPCreateNode(UINT8 Type, UINT8 SubType, UINT16 Length)
+{
+ EFI_DEVICE_PATH_PROTOCOL *pDp;
+
+ if (Length<sizeof(EFI_DEVICE_PATH_PROTOCOL)) return NULL;
+ if ( !(pDp = MallocZ(Length)) ) return NULL;
+
+ pDp->Type = Type;
+ pDp->SubType = SubType;
+ SET_NODE_LENGTH(pDp,Length);
+ return pDp;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+BOOLEAN DPIsMultiInstance(EFI_DEVICE_PATH_PROTOCOL* pDp)
+{
+ if (!pDp) return FALSE;
+ return DPGetEndNode(pDp)->SubType != END_ENTIRE_SUBTYPE;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: TimerIsSet
+//
+// Description:
+// VOID TimerIsSet(IN EFI_EVENT Event, IN OUT VOID *Context)
+//
+// Input:
+//
+// Output:
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID TimerIsSet(EFI_EVENT Event, VOID *Context)
+{
+ *(BOOLEAN*)Context = TRUE;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: TimerStart
+//
+// Description:
+// EFI_EVENT TimerStart(OUT BOOLEAN *pTimerFlag, IN UINT64 Delay)
+//
+// Input:
+//
+// Output:
+//
+// Modified:
+//
+// Referrals:
+// TimerIsSet
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: TimerStop
+//
+// Description:
+// VOID TimerStop(IN BOOLEAN TimerFlag, IN EFI_EVENT Event)
+//
+// Input:
+//
+// Output:
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+void TimerStop(BOOLEAN TimerFlag, EFI_EVENT Event)
+{
+ if (!TimerFlag) pBS->SetTimer(Event, TimerCancel,0);
+ pBS->CloseEvent(Event);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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; i<Number; i++)
+ {
+ Status = FVReadFile(Handle[i], (EFI_GUID*)(pPath+1), &pSource, &Size);
+ if (!EFI_ERROR(Status)) break;
+ }
+ pBS->FreePool(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
+
+//*************************************************************************
+//<AMI_SHDR_START>
+//
+// 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.
+//
+//<AMI_SHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_SHDR_START>
+//
+// 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.
+//
+//<AMI_SHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+
+VOID DListInit(DLIST* pList){
+ pList->pHead = NULL;
+ pList->pTail = NULL;
+ pList->Size = 0;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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++;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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--;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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++;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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
+ );
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_STATUS LoadStrings(
+ EFI_HANDLE ImageHandle, EFI_HII_HANDLE *pHiiHandle
+)
+{
+ HII_UTILITIES_PROTOCOL *HiiUtilities = GetHiiUtilitiesInterface();
+ return
+ (HiiUtilities==NULL)
+ ? EFI_UNSUPPORTED
+ : HiiUtilities->LoadStrings(ImageHandle, pHiiHandle);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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
+ );
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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
+ );
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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
+ );
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_STATUS HiiLibGetGlyphWidth(
+ IN CHAR16 Char, OUT UINT16 *Width
+){
+ HII_UTILITIES_PROTOCOL *HiiUtilities = GetHiiUtilitiesInterface();
+ return
+ (HiiUtilities==NULL)
+ ? EFI_UNSUPPORTED
+ : HiiUtilities->GetGlyphWidth(Char, Width);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+#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; i<ResCount; i++){
+ Res=&ResTable[i];
+ //if all non existet space, Memory and IO has been converted to MMIO
+ //we don't want to hang on ERROR Status here
+ if(Res->Attributes==-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; i<ResCount; i++){
+ //Skip I/O
+ if(ResTable[i].Attributes==-1) continue;
+ //Set Attributes For this Region.
+ Status=pDxe->SetMemorySpaceAttributes(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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID DummyFunction(IN EFI_EVENT Event, IN VOID *Context) {}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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)) ;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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);
+ }
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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
+ );
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+BOOLEAN EFIAPI EfiAtRuntime ( VOID ) {return IsAtRuntime;}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+BOOLEAN EFIAPI EfiGoneVirtual ( VOID ) {return IsInVirtualMode;}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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 <efi.h>
+//
+// 1 2/19/04 12:54p Markw
+//
+//*************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: IO.c
+//
+// Description:
+// Contains generic I/O read/write functions.
+//
+//<AMI_FHDR_END>
+//*************************************************************************
+#include <amidxelib.h>
+
+//*************************************************************************
+//<AMI_GHDR_START>
+//
+// 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.
+//
+//<AMI_GHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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 @@
+<component>
+ name = "Library Sources"
+ category = ModulePart
+ LocalRoot = "Library\"
+ RefName = "LibSrc"
+[files]
+"LibSrc.sdl"
+[parts]
+"AmiLib"
+"AmiPeiLib"
+"AmiDxeLib"
+"AmiIa32Lib"
+"AmiX64Lib"
+<endComponent>
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 @@
+<component>
+ name = "Library"
+ category = ModulePart
+ LocalRoot = "Library\"
+ RefName = "Library"
+[files]
+"Library.sdl"
+"Tokens.c"
+"AmiLib.chm"
+<endComponent>
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 <AmiLib.h>
+
+
+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 <stddef.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#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 <stddef.h>
+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 <AmiDxeLib.h>
+#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;
+}
+
+//<AMI_PHDR_START>
+//--------------------------------------------------------------------------
+// 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
+//
+//--------------------------------------------------------------------------
+//<AMI_PHDR_END>
+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;
+}
+
+//<AMI_PHDR_START>
+//--------------------------------------------------------------------------
+// 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
+//
+//--------------------------------------------------------------------------
+//<AMI_PHDR_END>
+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
+//
+//*************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Memory.c
+//
+// Description:
+// Contains memory related library functions.
+//
+//<AMI_FHDR_END>
+//*************************************************************************
+#include <efi.h>
+#include <AmiLib.h>
+
+//*************************************************************************
+//<AMI_GHDR_START>
+//
+// 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.
+//
+//<AMI_GHDR_END>
+//*************************************************************************
+
+VOID CPULib_CpuID(IN UINT32 CpuIDIndex, OUT UINT32 *RegEAX, OUT UINT32 *RegEBX,
+ IN OUT UINT32 *RegECX, OUT UINT32 *RegEDX);
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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<end)
+ if (*d==*s){d++;s++;}
+ else return *d-*s;
+ return 0;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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
+//
+//*************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Misc.c
+//
+// Description:
+// Miscellaneous generic library functions.
+//
+//<AMI_FHDR_END>
+//*************************************************************************
+#include <HOB.h>
+#include <AmiLib.h>
+
+EFI_GUID gAmiGlobalVariableGuid = AMI_GLOBAL_VARIABLE_GUID;
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+ }
+ }
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+EFI_STATUS ExecScript(IO_DATA *ScriptData, UINTN EntryCount){
+ UINTN i;
+ EFI_STATUS Status;
+//----------------------
+ for(i=0; i<EntryCount;i++){
+ Status=IoWrite(ScriptData[i].Width, (UINT64)ScriptData[i].Addr,1,(VOID*)&ScriptData[i].Data);
+ if(EFI_ERROR(Status)) break;
+ }
+ 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/PELoader.c b/Library/PELoader.c
new file mode 100644
index 0000000..0a0673f
--- /dev/null
+++ b/Library/PELoader.c
@@ -0,0 +1,800 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (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/PELoader.c 15 7/10/09 3:49p Felixp $
+//
+// $Revision: 15 $
+//
+// $Date: 7/10/09 3:49p $
+//*************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/Library/PELoader.c $
+//
+// 15 7/10/09 3:49p Felixp
+// Function headers added
+//
+// 14 11/20/08 3:00p Felixp
+// ReallocatePeImage function is upadted to properly handle virtual
+// address fixups of the runtime images.
+//
+// 13 9/05/07 12:22p Felixp
+// GetName updated to support TE images.
+//
+// 12 9/05/07 2:38a Felixp
+// Boundary condition is IsTeImageValid routine is fixed.
+//
+// 11 8/02/07 1:35a Felixp
+// Always define GetDebugDirectory and GetName routines (used to be only
+// when EFI_DEBUG is defined). This is needed to support selective
+// debugging.
+//
+// 10 6/01/07 2:55p Felixp
+// GetDebugDirectory routine updated: TE image support added; unused code
+// removed.
+//
+// 9 3/12/07 10:58a Felixp
+// Bug fix in reallocation fixups of PE32+ images.
+//
+// 8 10/12/06 9:40a Felixp
+// SectionSize parameter of FindPeSection changed from UINT32 to UINTN
+//
+// 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 1/25/05 3:31p Felixp
+// handling of debug directory slightly changed
+//
+// 2 1/18/05 3:22p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 9 11/24/04 9:37a Felixp
+// NameAndEntryStr removed
+//
+// 8 11/10/04 5:13p Felixp
+// 1. IsTeImageValid added
+// 2. NameAndEntryStr added
+//
+// 4 1/30/04 5:02p Felixp
+// parameter order in memset changed
+//
+// 2 1/27/04 3:58a Felixp
+// Bug fixes and improvements as a part of PEI CORE integration
+//
+// 1 1/19/04 4:23p Felixp
+// PE and TE Loader
+//
+//*************************************************************************
+//<AMI_FHDR_START>
+//
+// 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.
+//
+//<AMI_FHDR_END>
+//*************************************************************************
+#include <amilib.h>
+/************************************************************************/
+/* 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
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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
+ ;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID* PEEntryPoint(VOID *p)
+{
+ UINT8 *q = (UINT8*)p;
+ return q+((OPTIONAL_HEADER*)((FILE_HEADER*)(q+*(UINT32*)(q+60)+4)+1))->AddressOfEntryPoint;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID* TEEntryPoint(VOID *p)
+{
+ EFI_TE_IMAGE_HEADER* pTE = (EFI_TE_IMAGE_HEADER*)p;
+ return (UINT8*)(pTE+1) + pTE->AddressOfEntryPoint - pTE->StrippedSize;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+OPTIONAL_HEADER* GetPeOptionalHeader(VOID *p)
+{
+ UINT8 *q = (UINT8*)p;
+ return (OPTIONAL_HEADER*)((FILE_HEADER*)(q+*(UINT32*)(q+60)+4)+1);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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(pBegin<pEnd){
+ FIXUP *pFixupInfo,*pEndOfBlock;
+ UINT8 *pFixupPage;
+ if (!pBegin->Size) return FALSE;
+ pFixupInfo = (FIXUP*)(pBegin+1);
+ pEndOfBlock = (FIXUP*)((UINT8*)pBegin+pBegin->Size);
+ pFixupPage = pcurrent + pBegin->VirtualAddress;
+ for(;pFixupInfo<pEndOfBlock;pFixupInfo++){
+ UINTN *pFixup = (UINTN*)(pFixupPage + pFixupInfo->Offset);
+ 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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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->SectionAlignment<sizeof(INTN)) return NULL;
+ pSection=(SECTION_HEADER*)((UINT8*)pOptHeader+pFileHeader->OptionalHeaderSize);
+ // 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;i<pFileHeader->NumberOfSections;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->VirtualSize<pSection->SizeOfRawData)?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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID* LoadPeImage(UINT8* pold, UINT8* pnew){
+ return LoadPeImageEx(pold,pnew,NULL);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;i<pFileHeader->NumberOfSections;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
+//
+//*************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: PeiLib.c
+//
+// Description:
+// Contains an assortment of localized PEI library functions.
+//
+//<AMI_FHDR_END>
+//*************************************************************************
+
+#include <Token.h>
+#include <AmiPeiLib.h>
+#include <StatusCodes.h>
+#include <AmiHobs.h>
+#include <PPI/ReadOnlyVariable2.h>
+#include <PPI/LoadFile.h>
+#include <Protocol/Performance.h>
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+
+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);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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
+ );
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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
+ );
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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
+//
+//
+//*************************************************************************
+//<INT:AMI_FHDR_START>
+//
+// Name: Print.c
+//
+// Description:
+// Contains functions which convert device paths to strings.
+//
+//<INT:AMI_FHDR_END>
+//*************************************************************************
+
+#include <Protocol\DevicePath.h>
+#include <AmiDxeLib.h>
+
+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
+};
+
+//*************************************************************************
+//<INT:AMI_PHDR_START>
+//
+// 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.
+//
+//<INT:AMI_PHDR_END>
+//*************************************************************************
+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);
+}
+
+//*************************************************************************
+//<INT:AMI_PHDR_START>
+//
+// 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.
+//
+//<INT:AMI_PHDR_END>
+//*************************************************************************
+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);
+}
+
+//*************************************************************************
+//<INT:AMI_PHDR_START>
+//
+// 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.
+//
+//<INT:AMI_PHDR_END>
+//*************************************************************************
+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);
+}
+
+//*************************************************************************
+//<INT:AMI_PHDR_START>
+//
+// 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.
+//
+//<INT:AMI_PHDR_END>
+//*************************************************************************
+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);
+}
+
+//*************************************************************************
+//<INT:AMI_PHDR_START>
+//
+// 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.
+//
+//<INT:AMI_PHDR_END>
+//*************************************************************************
+UINTN UnknownToStr(
+ EFI_DEVICE_PATH_PROTOCOL *Path,
+ CHAR8 *Str
+ )
+{
+ return Sprintf(Str,DefaultDevicePath,Path->Type,Path->SubType);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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
+//
+//**********************************************************************
+
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// 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.
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#include <Token.h>
+#include <AmiDxeLib.h>
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)
+#include <Protocol/SmmAccess2.h>
+#else
+#include <Protocol/SmmAccess.h>
+#endif
+
+/// Internal list of SMRAM regions
+EFI_SMRAM_DESCRIPTOR *SmmAmiBufferValidationLibSmramRanges = NULL;
+
+/// Number of SMRAM regions in the internal list
+UINTN SmmAmiBufferValidationLibNumberOfSmramRange = 0;
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+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;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AmiValidateMmioBuffer(VOID* Buffer, UINTN BufferSize){
+ return AmiValidateMemoryBuffer(Buffer,BufferSize);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+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;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+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
+//
+//*************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: StdLibC.c
+//
+// Description:
+// StdLibC.c contains a number of standard C library functions, including
+// but not limited to string and cctype library functions.
+//
+//<AMI_FHDR_END>
+//*************************************************************************
+#include <AmiLib.h>
+
+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
+
+//*************************************************************************
+//<AMI_GHDR_START>
+//
+// 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.
+//
+//<AMI_GHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_GHDR_START>
+//
+// 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.
+//
+//<AMI_GHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_GHDR_START>
+//
+// 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.
+//
+//<AMI_GHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_GHDR_START>
+//
+// 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.
+//
+//<AMI_GHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_GHDR_START>
+//
+// 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.
+//
+//<AMI_GHDR_END>
+//*************************************************************************
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+int Toupper(int c) {
+ return (c>='a' && c<='z') ? c-'a'+'A' : c;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+UINTN Strlen(char *string) {
+ UINTN length=0;
+ while(*string++) length++;
+ return length;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+UINTN Wcslen(CHAR16 *string) {
+ UINTN length=0;
+ while(*string++) length++;
+ return length;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+char* Strcpy(char *string1,char *string2){
+ char *dest = string1;
+ while(*string1++=*string2++);
+ return dest;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+CHAR16* Wcscpy(CHAR16 *string1, CHAR16* string2){
+ CHAR16 *dest = string1;
+ while(*string1++=*string2++);
+ return dest;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+int Strcmp( char *string1, char *string2 ) {
+ while(*string1 && *string1==*string2) {*string1++;*string2++;}
+ return *string1 - *string2;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+int Wcscmp( CHAR16 *string1, CHAR16 *string2 ) {
+ while(*string1 && *string1==*string2) {*string1++;*string2++;}
+ return *string1 - *string2;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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<str2p) {
+ char temp=*strp;
+ *strp=*str2p;
+ *str2p=temp;
+ strp++;str2p--;
+ }
+ return string;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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!
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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!
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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 );
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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 );
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// 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.
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+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
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// 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
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#include <FFS.h>
+#include <AmiLib.h>
+#include <token.h>
+
+// 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
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: KbdIrqSupport
+//
+// Description: Variable to replace KB_IRQ_SUPPORT token.
+//
+// Notes: BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+BOOLEAN KbdIrqSupport =
+#ifdef KB_IRQ_SUPPORT
+ KB_IRQ_SUPPORT
+#else
+ 0
+#endif
+ ;
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: MsIrqSupport
+//
+// Description: Variable to replace MS_IRQ_SUPPORT token.
+//
+// Notes: BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+BOOLEAN MsIrqSupport =
+#ifdef MS_IRQ_SUPPORT
+ MS_IRQ_SUPPORT
+#else
+ 0
+#endif
+ ;
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: Ps2MouseSupport
+//
+// Description: Variable to replace PS2MOUSE_SUPPORT token.
+//
+// Notes: BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+BOOLEAN Ps2MouseSupport =
+#ifdef PS2MOUSE_SUPPORT
+ PS2MOUSE_SUPPORT
+#else
+ 0
+#endif
+ ;
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: Ps2KbdSupport
+//
+// Description: Variable to replace PS2KBD_SUPPORT token.
+//
+// Notes: BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+BOOLEAN Ps2KbdSupport =
+#ifdef PS2KBD_SUPPORT
+PS2KBD_SUPPORT
+#else
+ 0
+#endif
+ ;
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: KbRdBeforeInstall
+//
+// Description: Variable to replace KBD_READ_BEFORE_INSTALL token.
+//
+// Notes: BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+BOOLEAN KbRdBeforeInstall =
+#ifdef KBD_READ_BEFORE_INSTALL
+ KBD_READ_BEFORE_INSTALL
+#else
+ 0
+#endif
+ ;
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: KbcAutoDetectPorts
+//
+// Description: Variable to replace KBC_AUTODETECT_PORTS token.
+//
+// Notes: BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+BOOLEAN KbcAutoDetectPorts =
+#ifdef KBC_AUTODETECT_PORTS
+KBC_AUTODETECT_PORTS
+#else
+ 0
+#endif
+ ;
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: BlockKbcPin2223Bit
+//
+// Description: Variable to replace BLOCK_KBC_PIN_22_23_BIT token.
+//
+// Notes: BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+BOOLEAN BlockKbcPin2223Bit =
+#ifdef BLOCK_KBC_PIN_22_23_BIT
+BLOCK_KBC_PIN_22_23_BIT
+#else
+ 0
+#endif
+ ;
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: LedsAtStartup
+//
+// Description: Variable to replace LEDS_AT_STARTUP token.
+//
+// Notes: UINT8
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+UINT8 LedsAtStartup =
+#ifdef LEDS_AT_STARTUP
+LEDS_AT_STARTUP
+#else
+ 0
+#endif
+ ;
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: MaxHotKeys
+//
+// Description: Variable to replace MAX_HOTKEYS token.
+//
+// Notes: UINT8
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+UINT8 MaxHotKeys =
+#ifdef MAX_HOTKEYS
+MAX_HOTKEYS
+#else
+ 0
+#endif
+ ;
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: InitDefaultHotKeys
+//
+// Description: Variable to replace INIT_DEFAULT_HOTKEYS token.
+//
+// Notes: BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+BOOLEAN InitDefaultHotKeys =
+#ifdef INIT_DEFAULT_HOTKEYS
+INIT_DEFAULT_HOTKEYS
+#else
+ 0
+#endif
+ ;
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: KbcBasicAssuranceTest
+//
+// Description: Variable to replace KBC_BASIC_ASSURANCE_TEST token.
+//
+// Notes: BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+BOOLEAN KbcBasicAssuranceTest =
+#ifdef KBC_BASIC_ASSURANCE_TEST
+KBC_BASIC_ASSURANCE_TEST
+#else
+ 0
+#endif
+ ;
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: DetectPs2KeyboardValue
+//
+// Description: Variable to replace DETECT_PS2_KEYBOARD token.
+//
+// Notes: BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+BOOLEAN DetectPs2KeyboardValue =
+#ifdef DETECT_PS2_KEYBOARD
+DETECT_PS2_KEYBOARD
+#else
+ 0
+#endif
+ ;
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: DetectPs2MouseValue
+//
+// Description: Variable to replace DETECT_PS2_MOUSE token.
+//
+// Notes: BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+BOOLEAN DetectPs2MouseValue =
+#ifdef DETECT_PS2_MOUSE
+DETECT_PS2_MOUSE
+#else
+ 0
+#endif
+ ;
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: InstallKeyboardMouseAlways
+//
+// Description: Variable to replace INSTALL_KEYBOARD_MOUSE_ALWAYS token.
+//
+// Notes: BOOLEAN
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+BOOLEAN InstallKeyboardMouseAlways =
+#ifdef INSTALL_KEYBOARD_MOUSE_ALWAYS
+INSTALL_KEYBOARD_MOUSE_ALWAYS
+#else
+ 0
+#endif
+ ;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: IbFreeTimeoutValue
+//
+// Description: Variable to replace IBFREE_TIMEOUT token.
+//
+// Notes: UINT32
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+UINT32 IbFreeTimeoutValue =
+#ifdef IBFREE_TIMEOUT
+IBFREE_TIMEOUT
+#else
+ 0
+#endif
+ ;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: IbMaxFreeTimeoutValue
+//
+// Description: Variable to replace MAXIMUM_TIMEOUT_FOR_IBFREE token.
+//
+// Notes: UINT32
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+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 **
+//** **
+//**********************************************************************
+//**********************************************************************