summaryrefslogtreecommitdiff
path: root/Core/EM/Capsule2_0
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 /Core/EM/Capsule2_0
downloadzprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'Core/EM/Capsule2_0')
-rw-r--r--Core/EM/Capsule2_0/Capsule2_0.c870
-rw-r--r--Core/EM/Capsule2_0/Capsule2_0.cif13
-rw-r--r--Core/EM/Capsule2_0/Capsule2_0.h177
-rw-r--r--Core/EM/Capsule2_0/Capsule2_0.mak70
-rw-r--r--Core/EM/Capsule2_0/Capsule2_0.sdl60
-rw-r--r--Core/EM/Capsule2_0/Capsule2_0Bds.c140
-rw-r--r--Core/EM/Capsule2_0/Capsule2_0Runtime.c457
7 files changed, 1787 insertions, 0 deletions
diff --git a/Core/EM/Capsule2_0/Capsule2_0.c b/Core/EM/Capsule2_0/Capsule2_0.c
new file mode 100644
index 0000000..e29e544
--- /dev/null
+++ b/Core/EM/Capsule2_0/Capsule2_0.c
@@ -0,0 +1,870 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (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/Core/EM/Capsule2_0/Capsule2_0.c 3 4/16/14 3:12a Chaseliu $
+//
+// $Revision: 3 $
+//
+// $Date: 4/16/14 3:12a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/Capsule2_0/Capsule2_0.c $
+//
+// 3 4/16/14 3:12a 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
+//
+// 2 4/16/13 5:42a Thomaschen
+// Fixed for EIP106722.
+//
+// 7 3/07/14 5:14p Artems
+// EIP 154318
+// Added fixes addressed in review comment
+//
+// 6 2/28/14 5:54p Artems
+// EIP 154318: fixed vulnerability with capsule block descriptors count
+// overflow
+//
+// 5 2/07/13 5:18p Artems
+// [TAG] EIP106722
+// [Category] Bug Fix
+// [Severity] Critical
+// [Symptom] Win8 firmware update doesn't work
+// [RootCause] For Win8 update capsule CapsuleRecovery device didn't
+// skip capsule header
+// [Solution] Added unique GUID to distinguish between AFU and Win8
+// capsule update
+// [Files] Capsule2_0.c CapsuleRecovery.c Capsule.h
+//
+// 4 11/30/12 6:10p Artems
+// [TAG] EIP107134
+// [Category] Improvement
+// [Description] Potential security holes in Aptio 4 Capsule eModule
+// [Files] Capsule2_0.c
+//
+// 3 7/31/12 6:18p Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Added support for APTIO_FW_UPDATE capsule
+// [Files] Capsule2_0.c
+//
+// 2 7/20/12 10:44a Artems
+// [TAG] EIP93520
+// [Category] New Feature
+// [Description] Support of Microsoft ESRT spec
+// [Files] Capsule.c
+//
+// 1 5/24/12 4:22p Artems
+// [TAG] EIP74625
+// [Category] New Feature
+// [Description] New Capsule PPI required by latest Intel's MRC code
+// [Files] Capsule2_0.cif
+// Capsule2_0.sdl
+// Capsule2_0.mak
+// Capsule2_0.c
+// Capsule2_0.h
+// Capsule2_0Runtime.c
+// Capsule2_0Bds.c
+//
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Capsule2_0.c
+//
+// Description: Capsule PPI implementation
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#include <AmiPeiLib.h>
+#include <AmiHobs.h>
+#include <Capsule.h>
+#include <Ppi/Capsule.h>
+#include "Capsule2_0.h"
+
+static EFI_GUID CapsuleVariableGuid = EFI_CAPSULE_AMI_GUID;
+static EFI_GUID AmiCapsuleHobGuid = AMI_CAPSULE_HOB_GUID;
+
+static PEI_CAPSULE_PPI CapsulePpi = {
+ CoreCapsuleCoalesce,
+ CoreCheckCapsuleUpdate,
+ CoreCapsuleCreateState
+};
+
+static EFI_PEI_PPI_DESCRIPTOR PpiList[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gPeiCapsulePpiGuid,
+ &CapsulePpi
+ }
+};
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: Capsule20PeiInit
+//
+// Description:
+// This function installs capsule PPI
+//
+// Input:
+// IN EFI_FFS_FILE_HEADER *FfsHeader - pointer to this file header
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI_SERVICES
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS EFIAPI Capsule20PeiInit (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+)
+{
+ EFI_STATUS Status;
+
+ Status = CoreCheckCapsuleUpdate(PeiServices);
+ if(!EFI_ERROR(Status))
+ Status = (*PeiServices)->InstallPpi(PeiServices, PpiList);
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CoreCapsuleCoalesce
+//
+// Description:
+// This function coalesces capsule data in continuous block of memory
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI_SERVICES
+// IN OUT VOID **MemoryBase - pointer to start of available memory
+// IN OUT UINTN *MemSize - pointer to available memory size
+//
+// Output:
+// EFI_SUCCESS - capsule coalesced successfully
+// EFI_ERROR - not enough memory to complete operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CoreCapsuleCoalesce (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT VOID **MemoryBase,
+ IN OUT UINTN *MemSize
+)
+{
+ EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr;
+ UINTN Size;
+ EFI_STATUS Status;
+ VOID *Start = *MemoryBase;
+ UINTN BufferSize = *MemSize;
+ UINTN NoOfChunks;
+
+ Ptr = GetCapsuleLocation(PeiServices);
+ if(Ptr == NULL)
+ return EFI_NOT_FOUND;
+
+ Size = GetCapsuleDataSize(Ptr, &NoOfChunks);
+ if(Size == 0 || Size > MAX_CAPSULE_SIZE)
+ return EFI_NOT_FOUND;
+
+ if(Size > BufferSize)
+ return EFI_BUFFER_TOO_SMALL;
+
+/* First try to find continuous block, not overlapped with capsule data */
+ Status = FindFreeBuffer(Ptr, Size, &Start, BufferSize, TRUE);
+ if(!EFI_ERROR(Status)) {
+ CoalesceCapsule(Ptr, Start, Size);
+ *MemoryBase = Start;
+ *MemSize = Size;
+ return EFI_SUCCESS;
+ }
+
+/* Large enough buffer not found try to coalesce capsule piece by piece */
+/* Get buffer to store mailbox information */
+/* we will allocate buffer from the bottom of available memory */
+ Status = FindFreeBuffer(Ptr, sizeof(CAPSULE_BLOCK) * NoOfChunks, &Start, BufferSize, FALSE);
+ if(EFI_ERROR(Status))
+ return Status;
+/* recalculate available buffer size */
+ BufferSize = (UINTN)Start - (UINTN)(*MemoryBase);
+ if(Size > BufferSize)
+ return EFI_BUFFER_TOO_SMALL;
+
+/* store mailbox info for future use */
+ SaveCapsulePointers(Ptr, NoOfChunks, (CAPSULE_BLOCK *)Start);
+
+ Status = CoalesceCapsuleByParts((CAPSULE_BLOCK *)Start, NoOfChunks, *MemoryBase, BufferSize);
+ if(!EFI_ERROR(Status)) {
+ *MemSize = Size; //since we will coalesce from start of available memory *MemoryBase value will be valid
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CoreCheckCapsuleUpdate
+//
+// Description:
+// This function checks if capsule is present
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI_SERVICES
+//
+// Output:
+// EFI_SUCCESS - capsule present
+// EFI_NOT_FOUND - capsule not present or is beyond the 4GB boundaries
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CoreCheckCapsuleUpdate (
+ IN EFI_PEI_SERVICES **PeiServices
+)
+{
+ EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr;
+
+ Ptr = GetCapsuleLocation(PeiServices);
+ return (Ptr == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CoreCapsuleCreateState
+//
+// Description:
+// This function copies coalesced capsule into reserved block of memory and creates HOB
+// with capsule parameters
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI_SERVICES
+// IN VOID *CapsuleBase - coalesced capsule start address
+// IN UINTN CapsuleSize - capsule size
+//
+// Output:
+// EFI_SUCCESS - capsule present
+// EFI_ERROR - not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CoreCapsuleCreateState(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN VOID *CapsuleBase,
+ IN UINTN CapsuleSize
+)
+{
+ EFI_STATUS Status;
+ UINTN TotalSize = 0;
+ EFI_CAPSULE_HEADER *Cap;
+ VOID *SaveCap;
+ AMI_CAPSULE_HOB *Hob;
+ UINTN Pages;
+ EFI_PHYSICAL_ADDRESS Save;
+ static EFI_GUID AmiFwCapsuleGuid = APTIO_FW_CAPSULE_GUID;
+ static EFI_GUID W8FwUpdateImageCapsuleGuid = W8_FW_UPDATE_IMAGE_CAPSULE_GUID;
+
+ static EFI_GUID RecoveryBootModeGuid = EFI_PEI_BOOT_IN_RECOVERY_MODE_PEIM_PPI;
+ static EFI_PEI_PPI_DESCRIPTOR RecoveryModePpi = {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &RecoveryBootModeGuid, NULL
+ };
+
+ Cap = (EFI_CAPSULE_HEADER *)CapsuleBase;
+
+ while(TotalSize < CapsuleSize) {
+ Pages = EFI_SIZE_TO_PAGES(Cap->CapsuleImageSize);
+ Status = (*PeiServices)->AllocatePages(PeiServices, EfiBootServicesData, Pages, &Save);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ SaveCap = (VOID *)(UINTN)Save;
+ MemCpy(SaveCap, Cap, Cap->CapsuleImageSize);
+
+ Status = (*PeiServices)->CreateHob(PeiServices, EFI_HOB_TYPE_GUID_EXTENSION, sizeof(AMI_CAPSULE_HOB), &Hob);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ Hob->Header.Name = AmiCapsuleHobGuid;
+ Hob->CapsuleData = (EFI_PHYSICAL_ADDRESS)(UINTN)SaveCap;
+ Hob->CapsuleGuid = Cap->CapsuleGuid;
+ Hob->CapsuleLength = Cap->CapsuleImageSize;
+
+ if(!guidcmp(&(Cap->CapsuleGuid), &AmiFwCapsuleGuid) ||
+ !guidcmp(&(Cap->CapsuleGuid), &W8FwUpdateImageCapsuleGuid)) {
+ (*PeiServices)->SetBootMode(PeiServices, BOOT_ON_FLASH_UPDATE);
+ (*PeiServices)->InstallPpi(PeiServices, &RecoveryModePpi);
+ }
+
+ TotalSize += Cap->CapsuleImageSize;
+ (UINT8 *)Cap += Cap->CapsuleImageSize;
+ }
+ return EFI_SUCCESS;
+}
+
+
+/* ----------- Capsule service functions ------------ */
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetCapsuleLocation
+//
+// Description:
+// This function returns pointer to capsule mailbox
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI_SERVICES
+//
+// Output:
+// EFI_CAPSULE_BLOCK_DESCRIPTOR * - pointer to mailbox, or NULL
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_CAPSULE_BLOCK_DESCRIPTOR * GetCapsuleLocation(
+ IN EFI_PEI_SERVICES **PeiServices
+)
+{
+ EFI_STATUS Status;
+ UINTN VarSize = sizeof (EFI_PHYSICAL_ADDRESS);
+ EFI_PHYSICAL_ADDRESS MailBox = 0;
+
+ Status = PeiGetVariable(PeiServices, CAPSULE_UPDATE_VAR, &CapsuleVariableGuid, NULL, &VarSize, &MailBox);
+ PEI_TRACE((-1, PeiServices, "Get capsule variable %r, addr %lx\n", Status, MailBox));
+ if(EFI_ERROR(Status))
+ return NULL;
+
+ if(MailBox >= MAX_CAPSULE_ADDRESS)
+ return NULL; //no support for Capsule above 4GB
+
+ return (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)MailBox;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetCapsuleDataSize
+//
+// Description:
+// This function returns capsule size calculated from mailbox data
+//
+// Input:
+// IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr - pointer to capsule mailbox
+// OUT UINTN *NoOfChunks - pointer where to store quantity of capsule pieces
+//
+// Output:
+// UINTN - capsule size in bytes or 0
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN GetCapsuleDataSize(
+ IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr,
+ OUT UINTN *NoOfChunks
+)
+{
+ UINT64 Result = 0;
+ UINTN Chunks = 0;
+
+ do {
+ if(Ptr->DataBlock >= MAX_CAPSULE_ADDRESS) //pointer above 4GB
+ return 0;
+
+ if(Ptr->Length != 0) {
+ if(Ptr->Length > MAX_CAPSULE_SIZE - Result)
+ return 0;
+ Result += Ptr->Length;
+ Chunks++;
+ Ptr++;
+ } else if (Ptr->DataBlock != NULL) {
+ if(Ptr == (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)(Ptr->ContinuationPointer))
+ //when continuation pointer points to itself it's either error or malicious capsule, we won't process it
+ return 0;
+ Ptr = (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)(Ptr->ContinuationPointer);
+ } else {
+ break;
+ }
+ } while(Chunks <= MAX_CAPSULE_BLOCK_DESCRIPTOR_COUNT);
+
+ if(Chunks <= MAX_CAPSULE_BLOCK_DESCRIPTOR_COUNT) {
+ *NoOfChunks = Chunks;
+ return (UINTN)Result;
+ } else
+ return 0;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BufferOverlap
+//
+// Description:
+// This function checks if two buffers overlap each other
+//
+// Input:
+// IN MEMORY_BLOCK *Buffer1 - buffer1 parameters
+// IN MEMORY_BLOCK *Buffer2 - buffer2 parameters
+//
+// Output:
+// TRUE - buffers overlap, FALSE otherwise
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN BufferOverlap(
+ IN MEMORY_BLOCK *Buffer1,
+ IN MEMORY_BLOCK *Buffer2
+)
+{
+ return ((Buffer2->Address > (Buffer1->Address + Buffer1->Size)) ||
+ (Buffer1->Address > (Buffer2->Address + Buffer2->Size))) ? FALSE : TRUE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AdjustBuffer
+//
+// Description:
+// This function moves one block of memory within free range to avoid overlap
+// with another buffer
+//
+// Input:
+// IN MEMORY_BLOCK *Free - free memory range parameters
+// IN MEMORY_BLOCK *Unmovable - parameters of overlapping buffer that can't be moved
+// IN OUT MEMORY_BLOCK *Movable - parameters of overlapping buffer that can be moved
+// IN BOOLEAN FromTop - flag of moving direction in free range(TRUE - move from top, FALSE -
+// move from bottom
+//
+// Output:
+// EFI_SUCCESS - buffer moved successfully
+// EFI_BUFFER_TOO_SMALL - not enough memory to move buffer
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AdjustBuffer(
+ IN MEMORY_BLOCK *Free,
+ IN MEMORY_BLOCK *Unmovable,
+ IN OUT MEMORY_BLOCK *Movable,
+ IN BOOLEAN FromTop
+)
+{
+ if(!BufferOverlap(Unmovable, Movable))
+ return EFI_SUCCESS;
+
+ if(FromTop) {
+/* Move movable block to the end of unmovalbe */
+ Movable->Address = Unmovable->Address + Unmovable->Size;
+ } else {
+/* Move movable block before unmovable */
+ Movable->Address = Unmovable->Address - Movable->Size;
+ }
+
+ return (BufferOverlap(Unmovable, Free)) ? EFI_BUFFER_TOO_SMALL : EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindFreeBuffer
+//
+// Description:
+// This function searches for free continuous block of memory of required size
+//
+// Input:
+// IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr - pointer to capsule mailbox
+// IN UINTN RequiredSize - size of buffer required
+// IN OUT VOID **BaseAddress - on input pointer to start of free memory, on output
+// start of requested buffer
+// IN UINTN AvailableSize - size of free memory
+// IN BOOLEAN FromTop - flag of moving direction in free range(TRUE - move from top, FALSE -
+// move from bottom
+//
+// Output:
+// EFI_SUCCESS - buffer moved successfully
+// EFI_BUFFER_TOO_SMALL - not enough memory to move buffer
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FindFreeBuffer(
+ IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr,
+ IN UINTN RequiredSize,
+ IN OUT VOID **BaseAddress,
+ IN UINTN AvailableSize,
+ IN BOOLEAN FromTop
+)
+{
+ EFI_STATUS Status;
+ MEMORY_BLOCK FreeMemory;
+ MEMORY_BLOCK RequiredMemory;
+ MEMORY_BLOCK Unmovable;
+
+ FreeMemory.Address = (UINT32)(UINTN)(*BaseAddress);
+ FreeMemory.Size = AvailableSize;
+
+ RequiredMemory.Size = RequiredSize;
+
+ if(FromTop) {
+/* start looking for available space from the top of available buffer */
+ RequiredMemory.Address = FreeMemory.Address;
+ } else {
+/* start looking for available space from the bottom of available buffer */
+ RequiredMemory.Address = AvailableSize - RequiredSize;
+ }
+
+ do {
+ /* First check if we overlapped with mailbox itself */
+ Unmovable.Address = (UINT32)Ptr;
+ Unmovable.Size = sizeof(EFI_CAPSULE_BLOCK_DESCRIPTOR);
+ Status = AdjustBuffer(&FreeMemory, &Unmovable, &RequiredMemory, FromTop);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ if(Ptr->Length != 0) {
+ /* Now check if we overlapped with DataBlock */
+ Unmovable.Address = (UINT32)(Ptr->DataBlock);
+ Unmovable.Size = (UINT32)(Ptr->Length);
+ Status = AdjustBuffer(&FreeMemory, &Unmovable, &RequiredMemory, FromTop);
+ Ptr++;
+ } else if (Ptr->DataBlock != NULL) {
+ Ptr = (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)(Ptr->ContinuationPointer);
+ } else {
+ break; //we've reached end of mailbox
+ }
+ } while (!EFI_ERROR(Status));
+
+ if(!EFI_ERROR(Status)) {
+ *BaseAddress = (VOID *)(UINTN)RequiredMemory.Address;
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CoalesceCapsule
+//
+// Description:
+// This function coalesces capsule from mailbox to continuous block of memory
+//
+// Input:
+// IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr - pointer to capsule mailbox
+// IN VOID *Start - pointer to start of continuous block of memory
+// IN UINTN Size - size of continuous block of memory
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID CoalesceCapsule(
+ IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr,
+ IN VOID *Start,
+ IN UINTN Size
+)
+{
+ UINT8 *Walker = (UINT8 *)Start;
+ UINT64 Stop = 0;
+
+ do {
+ if(Ptr->Length != 0) {
+ MemCpy(Walker, (VOID *)(UINTN)(Ptr->DataBlock), (UINTN)Ptr->Length);
+ Walker += Ptr->Length;
+ Stop += Ptr->Length;
+ Ptr++;
+ } else if(Ptr->DataBlock != NULL) {
+ Ptr = (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)(Ptr->ContinuationPointer);
+ } else {
+ break; //we've reached end of mailbox
+ }
+ } while (Stop <= Size);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SaveCapsulePointers
+//
+// Description:
+// This function relocates and reformats capsule mailbox for further processing
+//
+// Input:
+// IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr - pointer to capsule mailbox
+// IN UINTN ArraySize - size of array to store capsule mailbox pointers
+// OUT CAPSULE_BLOCK *Array - pointer where to store capsule mailbox pointers
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID SaveCapsulePointers(
+ IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr,
+ IN UINTN ArraySize,
+ OUT CAPSULE_BLOCK *Array
+)
+{
+ UINTN i = 0;
+ do {
+ if(Ptr->Length != 0) {
+ Array[i].OriginalAddress = (UINT32)Ptr->DataBlock;
+ Array[i].Size = (UINT32)Ptr->Length;
+ Array[i].RelocatedAddress = 0;
+ Array[i].Attributes = 0;
+ i++;
+ Ptr++;
+ } else if(Ptr->DataBlock != NULL) {
+ Ptr = (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)(Ptr->ContinuationPointer);
+ } else {
+ break;
+ }
+ } while(i <= ArraySize);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindOverlaps
+//
+// Description:
+// This function checks if given memory block overlaps with other blocks of capsule
+//
+// Input:
+// IN CAPSULE_BLOCK *Array - pointer to capsule blocks array
+// IN UINTN ArraySize - size of array of capsule blocks
+// IN MEMORY_BLOCK *Probe - pointer to memory block to check against
+//
+// Output:
+// UINTN - number of overlaps found or 0 if there are no overlaps
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN FindOverlaps(
+ IN CAPSULE_BLOCK *Array,
+ IN UINTN ArraySize,
+ IN MEMORY_BLOCK *Probe
+)
+{
+ UINTN i;
+ MEMORY_BLOCK Unmovable;
+ UINTN Overlap = 0;
+
+ for(i = 0; i < ArraySize; i++) {
+ if(Array[i].Attributes & CAPSULE_BLOCK_PROCESSING ||
+ Array[i].Attributes & CAPSULE_BLOCK_DONE)
+ continue;
+
+ Unmovable.Address = (Array[i].Attributes & CAPSULE_BLOCK_RELOCATED) ?
+ Array[i].RelocatedAddress : Array[i].OriginalAddress;
+ Unmovable.Size = Array[i].Size;
+ if(BufferOverlap(&Unmovable, Probe)) {
+ Overlap++;
+ Array[i].Attributes |= CAPSULE_BLOCK_OVERLAPPING;
+ }
+ }
+ return Overlap;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindFreeBufferEx
+//
+// Description:
+// This function searches for continuous memory block in free range, and if not found
+// in already processed capsule blocks
+//
+// Input:
+// IN CAPSULE_BLOCK *Array - pointer to capsule blocks array
+// IN UINTN ArraySize - size of array of capsule blocks
+// IN MEMORY_BLOCK *Available - available memory block parameters
+// IN MEMORY_BLOCK *Reserved - occupied memory block parameters
+// IN OUT MEMORY_BLOCK *Free - parameters for block that requires allocation
+//
+// Output:
+// EFI_SUCCESS - block relocated successfully
+// EFI_BUFFER_TOO_SMALL - not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FindFreeBufferEx(
+ IN CAPSULE_BLOCK *Array,
+ IN UINTN ArraySize,
+ IN MEMORY_BLOCK *Available,
+ IN MEMORY_BLOCK *Reserved,
+ IN OUT MEMORY_BLOCK *Free
+)
+{
+ UINTN i;
+ MEMORY_BLOCK Unmovable;
+ EFI_STATUS Status;
+
+ Free->Address = Available->Address;
+
+ for(i = 0; i < ArraySize; i++) {
+ if(Array[i].Attributes & CAPSULE_BLOCK_PROCESSING ||
+ Array[i].Attributes & CAPSULE_BLOCK_DONE)
+ continue;
+
+ Unmovable.Address = (Array[i].Attributes & CAPSULE_BLOCK_RELOCATED) ?
+ Array[i].RelocatedAddress : Array[i].OriginalAddress;
+ Unmovable.Size = Array[i].Size;
+ Status = AdjustBuffer(Available, &Unmovable, Free, TRUE);
+ if(EFI_ERROR(Status))
+ break;
+ }
+
+ if(!EFI_ERROR(Status)) {
+ return Status; //buffer found
+ }
+/* try to find free space in previously processed chunks */
+ for(i = 0; i < ArraySize; i++) {
+ if(Array[i].Attributes & CAPSULE_BLOCK_PROCESSING || Free->Size > Array[i].Size)
+ continue;
+
+ if(Array[i].Attributes & CAPSULE_BLOCK_DONE &&
+ !(Array[i].Attributes & CAPSULE_BLOCK_RELOCATED) ) {
+ /* if chunk was processed but not relocated, original address may be free */
+ Free->Address = Array[i].OriginalAddress;
+ if(!BufferOverlap(Free, Reserved)) {
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ return EFI_BUFFER_TOO_SMALL;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: RelocateOverlaps
+//
+// Description:
+// This function moves capsule blocks that overlap with reserved block
+//
+// Input:
+// IN CAPSULE_BLOCK *Array - pointer to capsule blocks array
+// IN UINTN ArraySize - size of array of capsule blocks
+// IN MEMORY_BLOCK *Available - available memory block parameters
+// IN MEMORY_BLOCK *Reserved - occupied memory block parameters
+//
+// Output:
+// EFI_SUCCESS - block relocated successfully
+// EFI_BUFFER_TOO_SMALL - not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS RelocateOverlaps(
+ IN CAPSULE_BLOCK *Array,
+ IN UINTN ArraySize,
+ IN MEMORY_BLOCK *Available,
+ IN MEMORY_BLOCK *Reserved
+)
+{
+ UINTN i;
+ MEMORY_BLOCK Free;
+ VOID *Source;
+ EFI_STATUS Status;
+
+ for(i = 0; i < ArraySize; i++) {
+ if(!(Array[i].Attributes & CAPSULE_BLOCK_OVERLAPPING))
+ continue;
+
+ Free.Size = Array[i].Size;
+ Status = FindFreeBufferEx(Array, ArraySize, Available, Reserved, &Free);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ Source = (Array[i].Attributes & CAPSULE_BLOCK_RELOCATED) ?
+ (VOID *)Array[i].RelocatedAddress : (VOID *)Array[i].OriginalAddress;
+ MemCpy((VOID *)(Free.Address), Source, Array[i].Size);
+ Array[i].Attributes |= CAPSULE_BLOCK_RELOCATED;
+ Array[i].Attributes &= ~CAPSULE_BLOCK_OVERLAPPING;
+ Array[i].RelocatedAddress = Free.Address;
+ }
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CoalesceCapsuleByParts
+//
+// Description:
+// This function coalesces capsule from capsule blocks
+//
+// Input:
+// IN CAPSULE_BLOCK *Array - pointer to capsule blocks array
+// IN UINTN ArraySize - size of array of capsule blocks
+// IN VOID *Buffer - pointer to start of continuous block of memory
+// IN UINTN BufferSize - size of continuous block of memory
+//
+// Output:
+// EFI_SUCCESS - block relocated successfully
+// EFI_BUFFER_TOO_SMALL - not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CoalesceCapsuleByParts(
+ IN CAPSULE_BLOCK *Array,
+ IN UINTN ArraySize,
+ IN VOID *Buffer,
+ IN UINTN BufferSize
+)
+{
+ UINTN i;
+ UINTN Overlap;
+ VOID *Source;
+ EFI_STATUS Status;
+ MEMORY_BLOCK Available;
+ MEMORY_BLOCK Reserved;
+ MEMORY_BLOCK Current;
+
+ Current.Address = (UINT32)Buffer;
+ Reserved.Address = Current.Address;
+ Reserved.Size = 0;
+ Available.Size = BufferSize;
+
+ for(i = 0; i < ArraySize; i++) {
+ Array[i].Attributes |= CAPSULE_BLOCK_PROCESSING;
+ Current.Size = Array[i].Size;
+ Available.Address = Current.Address + Current.Size;
+ Available.Size -= Array[i].Size; //reserve space
+ Reserved.Size += Array[i].Size;
+ Overlap = FindOverlaps(Array, ArraySize, &Current);
+ if(Overlap > 0) {
+ Status = RelocateOverlaps(Array, ArraySize, &Available, &Reserved);
+ if(EFI_ERROR(Status))
+ return Status;
+ }
+
+ Source = (Array[i].Attributes & CAPSULE_BLOCK_RELOCATED) ?
+ (VOID *)(Array[i].RelocatedAddress) : (VOID *)(Array[i].OriginalAddress);
+ MemCpy((VOID *)(Current.Address), Source, Array[i].Size);
+ Current.Address += Array[i].Size;
+ Array[i].Attributes &= ~CAPSULE_BLOCK_PROCESSING;
+ Array[i].Attributes |= CAPSULE_BLOCK_DONE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/Capsule2_0/Capsule2_0.cif b/Core/EM/Capsule2_0/Capsule2_0.cif
new file mode 100644
index 0000000..b50f587
--- /dev/null
+++ b/Core/EM/Capsule2_0/Capsule2_0.cif
@@ -0,0 +1,13 @@
+<component>
+ name = "Capsule2_0"
+ category = ModulePart
+ LocalRoot = "Core\EM\Capsule2_0\"
+ RefName = "Capsule2_0"
+[files]
+"Capsule2_0.sdl"
+"Capsule2_0.mak"
+"Capsule2_0.c"
+"Capsule2_0.h"
+"Capsule2_0Runtime.c"
+"Capsule2_0Bds.c"
+<endComponent>
diff --git a/Core/EM/Capsule2_0/Capsule2_0.h b/Core/EM/Capsule2_0/Capsule2_0.h
new file mode 100644
index 0000000..10e804b
--- /dev/null
+++ b/Core/EM/Capsule2_0/Capsule2_0.h
@@ -0,0 +1,177 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/Modules/Capsule2_0/Capsule2_0.h 1 5/24/12 4:22p Artems $
+//
+// $Revision: 1 $
+//
+// $Date: 5/24/12 4:22p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/Modules/Capsule2_0/Capsule2_0.h $
+//
+// 1 5/24/12 4:22p Artems
+// [TAG] EIP74625
+// [Category] New Feature
+// [Description] New Capsule PPI required by latest Intel's MRC code
+// [Files] Capsule2_0.cif
+// Capsule2_0.sdl
+// Capsule2_0.mak
+// Capsule2_0.c
+// Capsule2_0.h
+// Capsule2_0Runtime.c
+// Capsule2_0Bds.c
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Capsule2_0.h
+//
+// Description: Capsule PPI functions definition
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#ifndef __HII_PRIVATE__H__
+#define __HII_PRIVATE__H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <Token.h>
+#include <Efi.h>
+
+#define MAX_CAPSULE_ADDRESS 0x100000000 //4GB
+
+#define CAPSULE_BLOCK_DONE 0x0001
+#define CAPSULE_BLOCK_RELOCATED 0x0002
+#define CAPSULE_BLOCK_PROCESSING 0x0004
+#define CAPSULE_BLOCK_OVERLAPPING 0x0008
+
+typedef struct {
+ UINT32 OriginalAddress;
+ UINT32 Size;
+ UINT32 RelocatedAddress;
+ UINT32 Attributes;
+} CAPSULE_BLOCK;
+
+typedef struct {
+ UINT32 Address;
+ UINT32 Size;
+} MEMORY_BLOCK;
+
+EFI_STATUS CoreCapsuleCoalesce(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT VOID **MemoryBase,
+ IN OUT UINTN *MemSize
+);
+
+EFI_STATUS CoreCheckCapsuleUpdate(
+ IN EFI_PEI_SERVICES **PeiServices
+);
+
+EFI_STATUS CoreCapsuleCreateState(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN VOID *CapsuleBase,
+ IN UINTN CapsuleSize
+);
+
+EFI_CAPSULE_BLOCK_DESCRIPTOR * GetCapsuleLocation(
+ IN EFI_PEI_SERVICES **PeiServices
+);
+
+UINTN GetCapsuleDataSize(
+ IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr,
+ OUT UINTN *NoOfChunks
+);
+
+BOOLEAN BufferOverlap(
+ IN MEMORY_BLOCK *Buffer1,
+ IN MEMORY_BLOCK *Buffer2
+);
+
+EFI_STATUS AdjustBuffer(
+ IN MEMORY_BLOCK *Free,
+ IN MEMORY_BLOCK *Unmovable,
+ IN OUT MEMORY_BLOCK *Movable,
+ IN BOOLEAN FromTop
+);
+
+EFI_STATUS FindFreeBuffer(
+ IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr,
+ IN UINTN RequiredSize,
+ IN OUT VOID **BaseAddress,
+ IN UINTN AvailableSize,
+ IN BOOLEAN FromTop
+);
+
+VOID CoalesceCapsule(
+ IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr,
+ IN VOID *Start,
+ IN UINTN Size
+);
+
+VOID SaveCapsulePointers(
+ IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr,
+ IN UINTN ArraySize,
+ OUT CAPSULE_BLOCK *Array
+);
+
+UINTN FindOverlaps(
+ IN CAPSULE_BLOCK *Array,
+ IN UINTN ArraySize,
+ IN MEMORY_BLOCK *Probe
+);
+
+EFI_STATUS FindFreeBufferEx(
+ IN CAPSULE_BLOCK *Array,
+ IN UINTN ArraySize,
+ IN MEMORY_BLOCK *Available,
+ IN MEMORY_BLOCK *Reserved,
+ OUT MEMORY_BLOCK *Free
+);
+
+EFI_STATUS RelocateOverlaps(
+ IN CAPSULE_BLOCK *Array,
+ IN UINTN ArraySize,
+ IN MEMORY_BLOCK *Available,
+ IN MEMORY_BLOCK *Reserved
+);
+
+EFI_STATUS CoalesceCapsuleByParts(
+ IN CAPSULE_BLOCK *Array,
+ IN UINTN ArraySize,
+ IN VOID *Buffer,
+ IN UINTN BufferSize
+);
+
+/****** DO NOT WRITE BELOW THIS LINE *******/
+#ifdef __cplusplus
+}
+#endif
+#endif
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//************************************************************************* \ No newline at end of file
diff --git a/Core/EM/Capsule2_0/Capsule2_0.mak b/Core/EM/Capsule2_0/Capsule2_0.mak
new file mode 100644
index 0000000..791ae3a
--- /dev/null
+++ b/Core/EM/Capsule2_0/Capsule2_0.mak
@@ -0,0 +1,70 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (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/Modules/Capsule2_0/Capsule2_0.mak 1 5/24/12 4:22p Artems $
+#
+# $Revision: 1 $
+#
+# $Date: 5/24/12 4:22p $
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Core/Modules/Capsule2_0/Capsule2_0.mak $
+#
+# 1 5/24/12 4:22p Artems
+# [TAG] EIP74625
+# [Category] New Feature
+# [Description] New Capsule PPI required by latest Intel's MRC code
+# [Files] Capsule2_0.cif
+# Capsule2_0.sdl
+# Capsule2_0.mak
+# Capsule2_0.c
+# Capsule2_0.h
+# Capsule2_0Runtime.c
+# Capsule2_0Bds.c
+#
+#
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: Capsule2_0.mak
+#
+# Description: Make file to create Capsule Driver
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+
+CORE_PEIBin : $(BUILD_DIR)\Capsule2_0.obj
+RUNTIMEBin : $(BUILD_DIR)\Capsule2_0Runtime.obj
+CORE_DXEBin : $(BUILD_DIR)\Capsule2_0Bds.obj
+
+CFLAGS=$(CFLAGS) /D\"OEM_PROCESS_CAPSULE_LIST=$(OemProcessCapsuleList)\"
+
+{$(Capsule2_0_DIR)}.c{$(BUILD_DIR)}.obj::
+ $(CC) $(CFLAGS) /Fo$(BUILD_DIR)\ $<
+
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
diff --git a/Core/EM/Capsule2_0/Capsule2_0.sdl b/Core/EM/Capsule2_0/Capsule2_0.sdl
new file mode 100644
index 0000000..ade3693
--- /dev/null
+++ b/Core/EM/Capsule2_0/Capsule2_0.sdl
@@ -0,0 +1,60 @@
+TOKEN
+ Name = Capsule2_0_SUPPORT
+ Value = 1
+ TokenType = Boolean
+ TargetH = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable Capsule2_0 support in Project"
+End
+
+PATH
+ Name = Capsule2_0_DIR
+ Help = "Path to Capsule2_0 Module in Project"
+End
+
+MODULE
+ Help = "Includes Capsule2_0.mak to Project"
+ File = "Capsule2_0.mak"
+End
+
+TOKEN
+ Name = "SUPPORT_UPDATE_CAPSULE_RESET"
+ Value = "1"
+ Help = "If ON - platform supports memory preserve across reset."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "MAX_CAPSULE_SIZE"
+ Value = "0x4000000"
+ Help = "Maximum size for capsule"
+ TokenType = Integer
+ TargetH = Yes
+End
+
+ELINK
+ Name = "Capsule20PeiInit,"
+ Parent = "PeiInitNV,"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "Capsule20RuntimeInit,"
+ Parent = "RuntimeInitialize"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ProcessCapsule,"
+ Parent = "ConnectRootBridgeHandles,"
+ InvokeOrder = BeforeParent
+End
+
+ELINK
+ Name = "OemProcessCapsuleList"
+ Help = "List of callback functions to be called to process OEM capsule"
+ InvokeOrder = ReplaceParent
+End
+
diff --git a/Core/EM/Capsule2_0/Capsule2_0Bds.c b/Core/EM/Capsule2_0/Capsule2_0Bds.c
new file mode 100644
index 0000000..cb3b1df
--- /dev/null
+++ b/Core/EM/Capsule2_0/Capsule2_0Bds.c
@@ -0,0 +1,140 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/Modules/Capsule2_0/Capsule2_0Bds.c 2 7/31/12 6:19p Artems $
+//
+// $Revision: 2 $
+//
+// $Date: 7/31/12 6:19p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/Modules/Capsule2_0/Capsule2_0Bds.c $
+//
+// 2 7/31/12 6:19p Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Remove Capsule mailbox from NVRAM once capsule is
+// processed
+// [Files] Capsule2_0Bds.c
+//
+// 1 5/24/12 4:22p Artems
+// [TAG] EIP74625
+// [Category] New Feature
+// [Description] New Capsule PPI required by latest Intel's MRC code
+// [Files] Capsule2_0.cif
+// Capsule2_0.sdl
+// Capsule2_0.mak
+// Capsule2_0.c
+// Capsule2_0.h
+// Capsule2_0Runtime.c
+// Capsule2_0Bds.c
+//
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------
+//
+// Name: Capsule2_0Bds.c
+//
+// Description: Capsule execution implementation
+//
+//----------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+//----------------------------------------------------------------------
+
+#include <Token.h>
+#include <AmiDxeLib.h>
+#include <AmiHobs.h>
+#include <Capsule.h>
+#include <Protocol/Capsule.h>
+
+
+typedef EFI_STATUS (OEM_PROCESS_CAPSULE) (EFI_CAPSULE_HEADER *Capsule);
+extern OEM_PROCESS_CAPSULE OEM_PROCESS_CAPSULE_LIST EndOfList;
+OEM_PROCESS_CAPSULE* OemProcessCapsuleList[] = { OEM_PROCESS_CAPSULE_LIST NULL };
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ProcessCapsule
+//
+// Description: Retrieve capsule and process it
+//
+// Input:
+// IN EFI_HANDLE ImageHandle - Image handle
+// IN EFI_SYSTEM_TABLE *SystemTable - pointer to system table
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID ProcessCapsule(
+ VOID
+)
+{
+ static EFI_GUID HobListGuid = HOB_LIST_GUID;
+ static EFI_GUID AmiCapsuleHobGuid = AMI_CAPSULE_HOB_GUID;
+ static EFI_GUID CapsuleVendorGuid = EFI_CAPSULE_AMI_GUID;
+ EFI_STATUS Status;
+ EFI_HOB_HANDOFF_INFO_TABLE *pHit;
+ UINTN i;
+ EFI_CAPSULE_HEADER *Capsule = NULL;
+ AMI_CAPSULE_HOB *CapsuleHob;
+ VOID *Save;
+
+
+ pHit = GetEfiConfigurationTable(pST, &HobListGuid);
+ if(EFI_ERROR(FindNextHobByGuid(&AmiCapsuleHobGuid, &pHit)))
+ return; //capsule HOB not found
+
+//capsule was found and coalesced, we have to kill mailbox
+ Status = pRS->SetVariable (
+ CAPSULE_UPDATE_VAR,
+ &CapsuleVendorGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ 0,
+ (VOID *) Capsule);
+
+ CapsuleHob = (AMI_CAPSULE_HOB *)pHit;
+ Capsule = (EFI_CAPSULE_HEADER *)(VOID *)(UINTN)(CapsuleHob->CapsuleData);
+ for(i = 0; OemProcessCapsuleList[i] != NULL; i++) {
+ Status = OemProcessCapsuleList[i](Capsule);
+ if(!EFI_ERROR(Status))
+ return; //capsule is processed by OEM hook
+ }
+
+ if(Capsule->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {
+ /* populate capsule via system table, move to runtime memory */
+ Status = pBS->AllocatePool(EfiRuntimeServicesData, (UINTN)(CapsuleHob->CapsuleLength), &Save);
+ if(EFI_ERROR(Status))
+ return;
+
+ MemCpy(Save, (VOID *)(UINTN)(CapsuleHob->CapsuleData), (UINTN)(CapsuleHob->CapsuleLength));
+ Status = pBS->InstallConfigurationTable(&(CapsuleHob->CapsuleGuid), Save);
+ }
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/Capsule2_0/Capsule2_0Runtime.c b/Core/EM/Capsule2_0/Capsule2_0Runtime.c
new file mode 100644
index 0000000..445fafc
--- /dev/null
+++ b/Core/EM/Capsule2_0/Capsule2_0Runtime.c
@@ -0,0 +1,457 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (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/Core/EM/Capsule2_0/Capsule2_0Runtime.c 1 10/02/15 4:32a Chienhsieh $
+//
+// $Revision: 1 $
+//
+// $Date: 10/02/15 4:32a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/Capsule2_0/Capsule2_0Runtime.c $
+//
+// 1 10/02/15 4:32a Chienhsieh
+// Update EIP225308
+//
+// 2 7/14/15 4:31p Artems
+// [TAG] EIP225308
+// [Category] Improvement
+// [Description] CAPSULE_UPDATE_VAR is not clear after WIN10 BSOD issue
+// capsule requriement.
+// [Files] Capsule2_0Runtime.c
+//
+// 1 5/24/12 4:22p Artems
+// [TAG] EIP74625
+// [Category] New Feature
+// [Description] New Capsule PPI required by latest Intel's MRC code
+// [Files] Capsule2_0.cif
+// Capsule2_0.sdl
+// Capsule2_0.mak
+// Capsule2_0.c
+// Capsule2_0.h
+// Capsule2_0Runtime.c
+// Capsule2_0Bds.c
+//
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------
+//
+// Name: Capsule2_0Runtime.c
+//
+// Description: Capsule runtime services implementation
+//
+//----------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+//----------------------------------------------------------------------
+
+#include <Token.h>
+#include <Protocol/LoadedImage.h>
+#include <AmiDxeLib.h>
+#include <Capsule.h>
+#include <Protocol/Capsule.h>
+
+//----------------------------------------------------------------------
+#ifndef MAX_CAPSULE_ADDRESS
+#define MAX_CAPSULE_ADDRESS 0x100000000 //4GB
+#endif
+
+static EFI_CAPSULE_RUNTIME_DATA mCapsuleRuntimeData = { NULL, FALSE };
+
+static EFI_GUID gCapsuleVendorGuid = EFI_CAPSULE_AMI_GUID;
+static EFI_GUID gDxeServicesTableGuid = DXE_SERVICES_TABLE_GUID;
+
+EFI_STATUS UpdateCapsule(
+ IN EFI_CAPSULE_HEADER **CapsuleHeaderArray,
+ IN UINTN CapsuleCount,
+ IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL
+);
+
+EFI_STATUS QueryCapsuleCapabilities(
+ IN EFI_CAPSULE_HEADER **CapsuleHeaderArray,
+ IN UINTN CapsuleCount,
+ OUT UINT64 *MaximumCapsuleSize,
+ OUT EFI_RESET_TYPE *ResetType
+);
+
+BOOLEAN SupportUpdateCapsuleReset (
+ VOID
+);
+
+VOID SupportCapsuleSize (
+ IN OUT UINT32 *MaxSizePopulate,
+ IN OUT UINT32 *MaxSizeNonPopulate
+);
+
+VOID CapsuleExitBootServices (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+);
+
+BOOLEAN ValidateSgl (
+ IN EFI_PHYSICAL_ADDRESS MailBox
+);
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: Capsule20RuntimeInit
+//
+// Description: Capsule runtime driver entry point
+//
+// Input:
+// IN EFI_HANDLE ImageHandle - Image handle
+// IN EFI_SYSTEM_TABLE *SystemTable - pointer to system table
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID Capsule20RuntimeInit(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_HANDLE Handle = NULL;
+ EFI_STATUS Status;
+
+ InitAmiLib(ImageHandle, SystemTable);
+
+ pRS->UpdateCapsule = UpdateCapsule;
+ pRS->QueryCapsuleCapabilities = QueryCapsuleCapabilities;
+
+ Status = pBS->CreateEvent (
+ EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,
+ TPL_NOTIFY,
+ CapsuleExitBootServices,
+ &mCapsuleRuntimeData,
+ &(mCapsuleRuntimeData.CapsuleExitBootServiceEvent) );
+
+ pBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiCapsuleArchProtocolGuid,
+ NULL,
+ NULL );
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UpdateCapsule
+//
+// Description: This code finds if the capsule needs reset to update, if no, update immediately.
+//
+// Input:
+// IN EFI_CAPSULE_HEADER **CapsuleHeaderArray - array of pointers to capsule headers passed in
+// IN UINTN CapsuleCount - number of capsule
+// IN EFI_PHYSICAL_ADDRESS ScatterGatherList - physical address of datablock list points to capsule
+//
+// Output: EFI_SUCCESS - capsule processed successfully
+// EFI_INVALID_PARAMETER - CapsuleCount is less than 1,CapsuleGuid is not supported
+// EFI_DEVICE_ERROR - capsule processing failed
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS UpdateCapsule (
+ IN EFI_CAPSULE_HEADER **CapsuleHeaderArray,
+ IN UINTN CapsuleCount,
+ IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL
+)
+{
+ UINTN ArrayNumber;
+ VOID *BufferPtr;
+ EFI_STATUS Status;
+ EFI_CAPSULE_HEADER *CapsuleHeader;
+
+ if ((CapsuleCount < 1) || (CapsuleCount > MAX_SUPPORT_CAPSULE_NUM)){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BufferPtr = NULL;
+ CapsuleHeader = NULL;
+
+ //
+ //Compare GUIDs with EFI_CAPSULE_GUID, if capsule header contains CAPSULE_FLAGS_PERSIST_ACROSS_RESET
+ //and CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flags,whatever the GUID is, the service supports.
+ //
+
+ for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
+ CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) &&
+ !(CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_INITIATE_RESET) &&
+ !(CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+// TODO: Add Oem porting hook to handle OEM-specific capsule
+ }
+
+ //
+ //Assume that capsules have the same flags on reseting or not.
+ //
+ CapsuleHeader = CapsuleHeaderArray[0];
+
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
+ //
+ //Check if the platform supports update capsule across a system reset
+ //
+ if (!SupportUpdateCapsuleReset()) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (!ValidateSgl(ScatterGatherList)) {
+ return EFI_INVALID_PARAMETER;
+ } else {
+ Status = pRS->SetVariable (
+ CAPSULE_UPDATE_VAR,
+ &gCapsuleVendorGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof (EFI_PHYSICAL_ADDRESS),
+ (VOID *) &ScatterGatherList );
+ if (Status != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_INITIATE_RESET) != 0) {
+ pRS->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);
+ EFI_DEADLOOP();
+ }
+
+ return EFI_SUCCESS;
+ }
+
+// TODO: Add Oem porting hook to handle OEM-specific capsule
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: QueryCapsuleCapabilities
+//
+// Description: This code is query about capsule capability
+//
+// Input:
+// IN EFI_CAPSULE_HEADER **CapsuleHeaderArray - array of pointers to capsule headers passed in
+// IN UINTN CapsuleCount - number of capsule
+// OUT UINT64 *MaximumCapsuleSize - pointer to store maximum supported capsule size
+// OUT EFI_RESET_TYPE *ResetType - reset type required by capsule
+//
+// Output: EFI_SUCCESS - capsule processed successfully
+// EFI_INVALID_PARAMETER - CapsuleCount is less than 1,CapsuleGuid is not supported,
+// MaximumCapsuleSize or ResetType are NULL
+// EFI_UNSUPPORTED - capsule type is not supported
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS QueryCapsuleCapabilities(
+ IN EFI_CAPSULE_HEADER **CapsuleHeaderArray,
+ IN UINTN CapsuleCount,
+ OUT UINT64 *MaximumCapsuleSize,
+ OUT EFI_RESET_TYPE *ResetType
+)
+{
+ UINTN ArrayNumber;
+ EFI_CAPSULE_HEADER *CapsuleHeader;
+ UINT32 MaxSizePopulate;
+ UINT32 MaxSizeNonPopulate;
+
+
+ if ((CapsuleCount < 1) || (CapsuleCount > MAX_SUPPORT_CAPSULE_NUM)){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((MaximumCapsuleSize == NULL) ||(ResetType == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CapsuleHeader = NULL;
+
+ //
+ //Compare GUIDs with EFI_CAPSULE_GUID, if capsule header contains CAPSULE_FLAGS_PERSIST_ACROSS_RESET
+ //and CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flags,whatever the GUID is ,the service supports.
+ //
+ for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
+ CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) &&
+ !(CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+//TODO add OEM hook to support OEM defined capsules
+ }
+
+ SupportCapsuleSize(&MaxSizePopulate,&MaxSizeNonPopulate);
+ //
+ //Assume that capsules have the same flags on reseting or not.
+ //
+ CapsuleHeader = CapsuleHeaderArray[0];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
+ //
+ //Check if the platform supports update capsule across a system reset
+ //
+ if (!SupportUpdateCapsuleReset()) {
+ return EFI_UNSUPPORTED;
+ }
+ *ResetType = EfiResetWarm;
+ *MaximumCapsuleSize = MaxSizePopulate;
+ } else {
+ *ResetType = EfiResetCold;
+ *MaximumCapsuleSize = MaxSizeNonPopulate;
+ }
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SupportUpdateCapsuleReset
+//
+// Description: This function returns if the platform supports update capsule across a system reset.
+//
+// Input: None
+//
+// Output: TRUE - memory can be preserved across reset
+// FALSE - memory integrity across reset is not guaranteed
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN SupportUpdateCapsuleReset (
+ VOID
+)
+{
+ return SUPPORT_UPDATE_CAPSULE_RESET;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SupportCapsuleSize
+//
+// Description: This code returns the max size capsule the platform supports.
+//
+// Input:
+// IN OUT UINT32 *MaxSizePopulate - max supported capsule size, that updated across reset
+// IN OUT UINT32 *MaxSizeNonPopulate - max supported capsule size for immediate update
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID SupportCapsuleSize (
+ IN OUT UINT32 *MaxSizePopulate,
+ IN OUT UINT32 *MaxSizeNonPopulate
+)
+{
+ //
+ //Here is a sample size, different platforms have different sizes.
+ //
+ *MaxSizePopulate = MAX_CAPSULE_SIZE;
+ *MaxSizeNonPopulate = MAX_CAPSULE_SIZE;
+ return;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CapsuleExitBootServices
+//
+// Description: Exit boot services event callback
+//
+// Input:
+// IN EFI_EVENT Event - Exit boot services event
+// IN VOID *Context - pointer to event context
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID CapsuleExitBootServices (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+)
+{
+ EFI_CAPSULE_RUNTIME_DATA *pCapsuleRuntimeData;
+ //
+ // Get our context
+ //
+ pCapsuleRuntimeData = (EFI_CAPSULE_RUNTIME_DATA *) Context;
+ pCapsuleRuntimeData->IsRuntimeMode = TRUE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ValidateSgl
+//
+// Description:
+// This function validates ScatterGatherList
+//
+// Input:
+// IN EFI_PHYSICAL_ADDRESS MailBox - address of the capsule mailbox
+//
+// Output:
+// TRUE - ScatterGatherList is valid, FALSE otherwise
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN ValidateSgl (
+ IN EFI_PHYSICAL_ADDRESS Mailbox
+)
+{
+ EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr;
+ UINTN Chunks = 0;
+ UINT64 Result = 0;
+
+ if (Mailbox >= MAX_CAPSULE_ADDRESS || Mailbox == 0)
+ return FALSE;
+
+ Ptr = (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)Mailbox;
+
+ do {
+ if(Ptr->DataBlock >= MAX_CAPSULE_ADDRESS) //pointer above 4GB
+ return FALSE;
+
+ if(Ptr->Length != 0) {
+ if(Ptr->Length > MAX_CAPSULE_SIZE - Result)
+ return FALSE;
+ Result += Ptr->Length;
+ Chunks++;
+ Ptr++;
+ } else if (Ptr->DataBlock != NULL) {
+ if(Ptr == (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)(Ptr->ContinuationPointer))
+ //when continuation pointer points to itself it's either error or malicious capsule, we won't process it
+ return FALSE;
+ Ptr = (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)(Ptr->ContinuationPointer);
+ } else {
+ break;
+ }
+ } while(Chunks <= MAX_CAPSULE_BLOCK_DESCRIPTOR_COUNT);
+
+ return (Chunks <= MAX_CAPSULE_BLOCK_DESCRIPTOR_COUNT) ? TRUE : FALSE;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file