summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/CapsulePei
diff options
context:
space:
mode:
authorGuo Mang <mang.guo@intel.com>2017-08-02 09:54:47 +0800
committerGuo Mang <mang.guo@intel.com>2017-09-05 19:45:08 +0800
commit6c128c65b5ec0e5b8b5a0ccb165f3afd29e485f8 (patch)
tree444372d92a0ae8991fe4d15eb3937df43690dfda /MdeModulePkg/Universal/CapsulePei
parentb207c6434d7a5a4502975d322312e07017e8a8cb (diff)
downloadedk2-platforms-6c128c65b5ec0e5b8b5a0ccb165f3afd29e485f8.tar.xz
Remove core packages since we can get them from edk2 repository
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang <mang.guo@intel.com>
Diffstat (limited to 'MdeModulePkg/Universal/CapsulePei')
-rw-r--r--MdeModulePkg/Universal/CapsulePei/Capsule.h130
-rw-r--r--MdeModulePkg/Universal/CapsulePei/CapsulePei.inf96
-rw-r--r--MdeModulePkg/Universal/CapsulePei/CapsulePei.unibin2114 -> 0 bytes
-rw-r--r--MdeModulePkg/Universal/CapsulePei/CapsulePeiExtra.unibin1364 -> 0 bytes
-rw-r--r--MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf59
-rw-r--r--MdeModulePkg/Universal/CapsulePei/CapsuleX64.unibin2838 -> 0 bytes
-rw-r--r--MdeModulePkg/Universal/CapsulePei/CapsuleX64Extra.unibin1382 -> 0 bytes
-rw-r--r--MdeModulePkg/Universal/CapsulePei/Common/CapsuleCoalesce.c1254
-rw-r--r--MdeModulePkg/Universal/CapsulePei/Common/CommonHeader.h102
-rw-r--r--MdeModulePkg/Universal/CapsulePei/UefiCapsule.c1063
-rw-r--r--MdeModulePkg/Universal/CapsulePei/X64/PageFaultHandler.S81
-rw-r--r--MdeModulePkg/Universal/CapsulePei/X64/PageFaultHandler.asm87
-rw-r--r--MdeModulePkg/Universal/CapsulePei/X64/X64Entry.c292
13 files changed, 0 insertions, 3164 deletions
diff --git a/MdeModulePkg/Universal/CapsulePei/Capsule.h b/MdeModulePkg/Universal/CapsulePei/Capsule.h
deleted file mode 100644
index 68d8e42745..0000000000
--- a/MdeModulePkg/Universal/CapsulePei/Capsule.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/** @file
-
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
-
-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.
-
-**/
-
-#ifndef _CAPSULE_PEIM_H_
-#define _CAPSULE_PEIM_H_
-
-#include <PiPei.h>
-#include <Uefi/UefiSpec.h>
-
-#include <Ppi/Capsule.h>
-#include <Ppi/LoadFile.h>
-#include <Ppi/ReadOnlyVariable2.h>
-#include <Guid/CapsuleVendor.h>
-
-#include <Library/DebugLib.h>
-#include <Library/PeimEntryPoint.h>
-#include <Library/PeiServicesLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/HobLib.h>
-#include <Library/PeiServicesTablePointerLib.h>
-#include <Library/PrintLib.h>
-#include <Library/PeCoffLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
-#include <Library/PcdLib.h>
-#include <Library/ReportStatusCodeLib.h>
-#include <Library/DebugAgentLib.h>
-#include <IndustryStandard/PeImage.h>
-#include "Common/CommonHeader.h"
-
-#ifdef MDE_CPU_IA32
-
-#pragma pack(1)
-
-//
-// Page-Map Level-4 Offset (PML4) and
-// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB
-//
-
-typedef union {
- struct {
- UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
- UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
- UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
- UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
- UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
- UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
- UINT64 Reserved:1; // Reserved
- UINT64 MustBeZero:2; // Must Be Zero
- UINT64 Available:3; // Available for use by system software
- UINT64 PageTableBaseAddress:40; // Page Table Base Address
- UINT64 AvabilableHigh:11; // Available for use by system software
- UINT64 Nx:1; // No Execute bit
- } Bits;
- UINT64 Uint64;
-} PAGE_MAP_AND_DIRECTORY_POINTER;
-
-//
-// Page Table Entry 2MB
-//
-typedef union {
- struct {
- UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
- UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
- UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
- UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
- UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
- UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
- UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page
- UINT64 MustBe1:1; // Must be 1
- UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
- UINT64 Available:3; // Available for use by system software
- UINT64 PAT:1; //
- UINT64 MustBeZero:8; // Must be zero;
- UINT64 PageTableBaseAddress:31; // Page Table Base Address
- UINT64 AvabilableHigh:11; // Available for use by system software
- UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution
- } Bits;
- UINT64 Uint64;
-} PAGE_TABLE_ENTRY;
-
-//
-// Page Table Entry 1GB
-//
-typedef union {
- struct {
- UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
- UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
- UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
- UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
- UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
- UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
- UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page
- UINT64 MustBe1:1; // Must be 1
- UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
- UINT64 Available:3; // Available for use by system software
- UINT64 PAT:1; //
- UINT64 MustBeZero:17; // Must be zero;
- UINT64 PageTableBaseAddress:22; // Page Table Base Address
- UINT64 AvabilableHigh:11; // Available for use by system software
- UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution
- } Bits;
- UINT64 Uint64;
-} PAGE_TABLE_1G_ENTRY;
-
-#pragma pack()
-
-typedef
-EFI_STATUS
-(*COALESCE_ENTRY) (
- IN EFI_PEI_SERVICES **PeiServices,
- IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList,
- IN OUT VOID **MemoryBase,
- IN OUT UINTN *MemorySize
- );
-
-#endif
-
-#endif
diff --git a/MdeModulePkg/Universal/CapsulePei/CapsulePei.inf b/MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
deleted file mode 100644
index d7aa37186f..0000000000
--- a/MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
+++ /dev/null
@@ -1,96 +0,0 @@
-## @file
-# Capsule update PEIM supports EFI and UEFI.
-#
-# Caution: This module requires additional review when modified.
-# This driver will have external input - capsule image.
-# This external input must be validated carefully to avoid security issue like
-# buffer overflow, integer overflow.
-#
-# Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
-#
-# 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.
-#
-##
-
-[Defines]
- INF_VERSION = 0x00010005
- BASE_NAME = CapsulePei
- MODULE_UNI_FILE = CapsulePei.uni
- FILE_GUID = C779F6D8-7113-4AA1-9648-EB1633C7D53B
- MODULE_TYPE = PEIM
- VERSION_STRING = 1.0
-
- ENTRY_POINT = CapsuleMain
-
-#
-# The following information is for reference only and not required by the build tools.
-#
-# VALID_ARCHITECTURES = IA32 X64 IPF EBC
-#
-
-[Sources]
- UefiCapsule.c
- Capsule.h
- Common/CapsuleCoalesce.c
-
-[Packages]
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
-
-
-[LibraryClasses]
- HobLib
- BaseMemoryLib
- PeiServicesLib
- PeimEntryPoint
- DebugLib
- PeiServicesTablePointerLib
- PrintLib
- ReportStatusCodeLib
-
-[LibraryClasses.IA32]
- PeCoffGetEntryPointLib
- PcdLib
- DebugAgentLib
-
-[Guids]
- ## SOMETIMES_CONSUMES ## Variable:L"CapsuleUpdateData"
- ## SOMETIMES_CONSUMES ## Variable:L"CapsuleLongModeBuffer"
- gEfiCapsuleVendorGuid
-
-[Ppis]
- gEfiPeiReadOnlyVariable2PpiGuid ## CONSUMES
- gEfiPeiCapsulePpiGuid ## PRODUCES
-
-[Ppis.IA32]
- gEfiPeiLoadFilePpiGuid ## SOMETIMES_CONSUMES
-
-[Pcd.IA32]
- gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleCoalesceFile ## SOMETIMES_CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES
-
-[FeaturePcd.IA32]
- gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES
-
-[Depex]
- gEfiPeiReadOnlyVariable2PpiGuid
-
-# [BootMode]
-# FLASH_UPDATE ## SOMETIMES_CONSUMES
-
-# [Hob.IA32]
-# UNDEFINED ## SOMETIMES_CONSUMES # CPU
-
-# [Hob]
-# UNDEFINED ## SOMETIMES_PRODUCES # UEFI_CAPSULE
-
-
-[UserExtensions.TianoCore."ExtraFiles"]
- CapsulePeiExtra.uni
diff --git a/MdeModulePkg/Universal/CapsulePei/CapsulePei.uni b/MdeModulePkg/Universal/CapsulePei/CapsulePei.uni
deleted file mode 100644
index c082315258..0000000000
--- a/MdeModulePkg/Universal/CapsulePei/CapsulePei.uni
+++ /dev/null
Binary files differ
diff --git a/MdeModulePkg/Universal/CapsulePei/CapsulePeiExtra.uni b/MdeModulePkg/Universal/CapsulePei/CapsulePeiExtra.uni
deleted file mode 100644
index 871be9b513..0000000000
--- a/MdeModulePkg/Universal/CapsulePei/CapsulePeiExtra.uni
+++ /dev/null
Binary files differ
diff --git a/MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf b/MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf
deleted file mode 100644
index 1630dfc383..0000000000
--- a/MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf
+++ /dev/null
@@ -1,59 +0,0 @@
-## @file
-# CapsuleX64 module handles >4GB capsule blocks.
-#
-# The X64 entrypoint to process capsule in long mode.
-# This module is built as X64.
-#
-# Caution: This module requires additional review when modified.
-# This driver will have external input - capsule image.
-# This external input must be validated carefully to avoid security issue like
-# buffer overflow, integer overflow.
-#
-# Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
-#
-# 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.
-#
-##
-
-[Defines]
- INF_VERSION = 0x00010005
- BASE_NAME = CapsuleX64
- MODULE_UNI_FILE = CapsuleX64.uni
- FILE_GUID = F7FDE4A6-294C-493c-B50F-9734553BB757
- MODULE_TYPE = PEIM
- VERSION_STRING = 1.0
-
-#
-# The following information is for reference only and not required by the build tools.
-#
-# VALID_ARCHITECTURES = X64
-#
-
-[Sources]
- X64/X64Entry.c
- X64/PageFaultHandler.asm
- X64/PageFaultHandler.S
- Common/CapsuleCoalesce.c
-
-[Packages]
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
-
-[LibraryClasses]
- BaseLib
- DebugLib
- CpuExceptionHandlerLib
- DebugAgentLib
-
-[Depex]
- FALSE
-
-[UserExtensions.TianoCore."ExtraFiles"]
- CapsuleX64Extra.uni
diff --git a/MdeModulePkg/Universal/CapsulePei/CapsuleX64.uni b/MdeModulePkg/Universal/CapsulePei/CapsuleX64.uni
deleted file mode 100644
index 10d3c4c5ce..0000000000
--- a/MdeModulePkg/Universal/CapsulePei/CapsuleX64.uni
+++ /dev/null
Binary files differ
diff --git a/MdeModulePkg/Universal/CapsulePei/CapsuleX64Extra.uni b/MdeModulePkg/Universal/CapsulePei/CapsuleX64Extra.uni
deleted file mode 100644
index 88d5e2057c..0000000000
--- a/MdeModulePkg/Universal/CapsulePei/CapsuleX64Extra.uni
+++ /dev/null
Binary files differ
diff --git a/MdeModulePkg/Universal/CapsulePei/Common/CapsuleCoalesce.c b/MdeModulePkg/Universal/CapsulePei/Common/CapsuleCoalesce.c
deleted file mode 100644
index d789fbbc75..0000000000
--- a/MdeModulePkg/Universal/CapsulePei/Common/CapsuleCoalesce.c
+++ /dev/null
@@ -1,1254 +0,0 @@
-/** @file
- The logic to process capsule.
-
- Caution: This module requires additional review when modified.
- This driver will have external input - capsule image.
- This external input must be validated carefully to avoid security issue like
- buffer overflow, integer overflow.
-
- CapsuleDataCoalesce() will do basic validation before coalesce capsule data
- into memory.
-
-(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
-Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
-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.
-
-**/
-
-#include <Uefi.h>
-#include <PiPei.h>
-
-#include <Guid/CapsuleVendor.h>
-
-#include <Library/BaseMemoryLib.h>
-#include <Library/DebugLib.h>
-#include <Library/PrintLib.h>
-#include <Library/BaseLib.h>
-
-#include "CommonHeader.h"
-
-#define MIN_COALESCE_ADDR (1024 * 1024)
-
-/**
- Given a pointer to the capsule block list, info on the available system
- memory, and the size of a buffer, find a free block of memory where a
- buffer of the given size can be copied to safely.
-
- @param BlockList Pointer to head of capsule block descriptors
- @param MemBase Pointer to the base of memory in which we want to find free space
- @param MemSize The size of the block of memory pointed to by MemBase
- @param DataSize How big a free block we want to find
-
- @return A pointer to a memory block of at least DataSize that lies somewhere
- between MemBase and (MemBase + MemSize). The memory pointed to does not
- contain any of the capsule block descriptors or capsule blocks pointed to
- by the BlockList.
-
-**/
-UINT8 *
-FindFreeMem (
- EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList,
- UINT8 *MemBase,
- UINTN MemSize,
- UINTN DataSize
- );
-
-/**
- Check the integrity of the capsule descriptors.
-
- @param BlockList Pointer to the capsule descriptors
-
- @retval NULL BlockList is not valid.
- @retval LastBlockDesc Last one Block in BlockList
-
-**/
-EFI_CAPSULE_BLOCK_DESCRIPTOR *
-ValidateCapsuleIntegrity (
- IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList
- );
-
-/**
- The capsule block descriptors may be fragmented and spread all over memory.
- To simplify the coalescing of capsule blocks, first coalesce all the
- capsule block descriptors low in memory.
-
- The descriptors passed in can be fragmented throughout memory. Here
- they are relocated into memory to turn them into a contiguous (null
- terminated) array.
-
- @param PeiServices pointer to PEI services table
- @param BlockList pointer to the capsule block descriptors
- @param NumDescriptors number of capsule data block descriptors, whose Length is non-zero.
- @param MemBase base of system memory in which we can work
- @param MemSize size of the system memory pointed to by MemBase
-
- @retval NULL could not relocate the descriptors
- @retval Pointer to the base of the successfully-relocated block descriptors.
-
-**/
-EFI_CAPSULE_BLOCK_DESCRIPTOR *
-RelocateBlockDescriptors (
- IN EFI_PEI_SERVICES **PeiServices,
- IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList,
- IN UINTN NumDescriptors,
- IN UINT8 *MemBase,
- IN UINTN MemSize
- );
-
-/**
- Check every capsule header.
-
- @param CapsuleHeader The pointer to EFI_CAPSULE_HEADER
-
- @retval FALSE Capsule is OK
- @retval TRUE Capsule is corrupted
-
-**/
-BOOLEAN
-IsCapsuleCorrupted (
- IN EFI_CAPSULE_HEADER *CapsuleHeader
- );
-
-/**
- Determine if two buffers overlap in memory.
-
- @param Buff1 pointer to first buffer
- @param Size1 size of Buff1
- @param Buff2 pointer to second buffer
- @param Size2 size of Buff2
-
- @retval TRUE Buffers overlap in memory.
- @retval FALSE Buffer doesn't overlap.
-
-**/
-BOOLEAN
-IsOverlapped (
- UINT8 *Buff1,
- UINTN Size1,
- UINT8 *Buff2,
- UINTN Size2
- );
-
-/**
- Given a pointer to a capsule block descriptor, traverse the list to figure
- out how many legitimate descriptors there are, and how big the capsule it
- refers to is.
-
- @param Desc Pointer to the capsule block descriptors
- @param NumDescriptors Optional pointer to where to return the number of capsule data descriptors, whose Length is non-zero.
- @param CapsuleSize Optional pointer to where to return the capsule image size
- @param CapsuleNumber Optional pointer to where to return the number of capsule
-
- @retval EFI_NOT_FOUND No descriptors containing data in the list
- @retval EFI_SUCCESS Return data is valid
-
-**/
-EFI_STATUS
-GetCapsuleInfo (
- IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Desc,
- IN OUT UINTN *NumDescriptors OPTIONAL,
- IN OUT UINTN *CapsuleSize OPTIONAL,
- IN OUT UINTN *CapsuleNumber OPTIONAL
- );
-
-/**
- Given a pointer to the capsule block list, info on the available system
- memory, and the size of a buffer, find a free block of memory where a
- buffer of the given size can be copied to safely.
-
- @param BlockList Pointer to head of capsule block descriptors
- @param MemBase Pointer to the base of memory in which we want to find free space
- @param MemSize The size of the block of memory pointed to by MemBase
- @param DataSize How big a free block we want to find
-
- @return A pointer to a memory block of at least DataSize that lies somewhere
- between MemBase and (MemBase + MemSize). The memory pointed to does not
- contain any of the capsule block descriptors or capsule blocks pointed to
- by the BlockList.
-
-**/
-UINT8 *
-FindFreeMem (
- EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList,
- UINT8 *MemBase,
- UINTN MemSize,
- UINTN DataSize
- )
-{
- UINTN Size;
- EFI_CAPSULE_BLOCK_DESCRIPTOR *CurrDesc;
- EFI_CAPSULE_BLOCK_DESCRIPTOR *TempDesc;
- UINT8 *MemEnd;
- BOOLEAN Failed;
-
- //
- // Need at least enough to copy the data to at the end of the buffer, so
- // say the end is less the data size for easy comparisons here.
- //
- MemEnd = MemBase + MemSize - DataSize;
- CurrDesc = BlockList;
- //
- // Go through all the descriptor blocks and see if any obstruct the range
- //
- while (CurrDesc != NULL) {
- //
- // Get the size of this block list and see if it's in the way
- //
- Failed = FALSE;
- TempDesc = CurrDesc;
- Size = sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
- while (TempDesc->Length != 0) {
- Size += sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
- TempDesc++;
- }
-
- if (IsOverlapped (MemBase, DataSize, (UINT8 *) CurrDesc, Size)) {
- //
- // Set our new base to the end of this block list and start all over
- //
- MemBase = (UINT8 *) CurrDesc + Size;
- CurrDesc = BlockList;
- if (MemBase > MemEnd) {
- return NULL;
- }
-
- Failed = TRUE;
- }
- //
- // Now go through all the blocks and make sure none are in the way
- //
- while ((CurrDesc->Length != 0) && (!Failed)) {
- if (IsOverlapped (MemBase, DataSize, (UINT8 *) (UINTN) CurrDesc->Union.DataBlock, (UINTN) CurrDesc->Length)) {
- //
- // Set our new base to the end of this block and start all over
- //
- Failed = TRUE;
- MemBase = (UINT8 *) ((UINTN) CurrDesc->Union.DataBlock) + CurrDesc->Length;
- CurrDesc = BlockList;
- if (MemBase > MemEnd) {
- return NULL;
- }
- }
- CurrDesc++;
- }
- //
- // Normal continuation -- jump to next block descriptor list
- //
- if (!Failed) {
- CurrDesc = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) CurrDesc->Union.ContinuationPointer;
- }
- }
- return MemBase;
-}
-
-/**
- Check the integrity of the capsule descriptors.
-
- @param BlockList Pointer to the capsule descriptors
-
- @retval NULL BlockList is not valid.
- @retval LastBlockDesc Last one Block in BlockList
-
-**/
-EFI_CAPSULE_BLOCK_DESCRIPTOR *
-ValidateCapsuleIntegrity (
- IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList
- )
-{
- EFI_CAPSULE_HEADER *CapsuleHeader;
- UINT64 CapsuleSize;
- UINTN CapsuleCount;
- EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr;
-
- DEBUG ((EFI_D_INFO, "ValidateCapsuleIntegrity\n"));
-
- //
- // Go through the list to look for inconsistencies. Check for:
- // * misaligned block descriptors.
- // * The first capsule header guid
- // * The first capsule header flag
- // * The first capsule header HeaderSize
- // * Length > MAX_ADDRESS
- // * ContinuationPointer > MAX_ADDRESS
- // * DataBlock + Length > MAX_ADDRESS
- //
- CapsuleSize = 0;
- CapsuleCount = 0;
- Ptr = BlockList;
-
- DEBUG ((EFI_D_INFO, "Ptr - 0x%x\n", Ptr));
- DEBUG ((EFI_D_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));
- DEBUG ((EFI_D_INFO, "Ptr->Union - 0x%x\n", Ptr->Union.ContinuationPointer));
- while ((Ptr->Length != 0) || (Ptr->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
- //
- // Make sure the descriptor is aligned at UINT64 in memory
- //
- if ((UINTN) Ptr & (sizeof(UINT64) - 1)) {
- DEBUG ((EFI_D_ERROR, "ERROR: BlockList address failed alignment check\n"));
- return NULL;
- }
- //
- // Sanity Check
- //
- if (Ptr->Length > MAX_ADDRESS) {
- DEBUG ((EFI_D_ERROR, "ERROR: Ptr->Length(0x%lx) > MAX_ADDRESS\n", Ptr->Length));
- return NULL;
- }
-
- if (Ptr->Length == 0) {
- //
- // Sanity Check
- //
- if (Ptr->Union.ContinuationPointer > MAX_ADDRESS) {
- DEBUG ((EFI_D_ERROR, "ERROR: Ptr->Union.ContinuationPointer(0x%lx) > MAX_ADDRESS\n", Ptr->Union.ContinuationPointer));
- return NULL;
- }
- //
- // Descriptor points to another list of block descriptors somewhere
- // else.
- //
- Ptr = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) Ptr->Union.ContinuationPointer;
- DEBUG ((EFI_D_INFO, "Ptr(C) - 0x%x\n", Ptr));
- DEBUG ((EFI_D_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));
- DEBUG ((EFI_D_INFO, "Ptr->Union - 0x%x\n", Ptr->Union.ContinuationPointer));
- } else {
- //
- // Sanity Check
- //
- if (Ptr->Union.DataBlock > (MAX_ADDRESS - (UINTN)Ptr->Length)) {
- DEBUG ((EFI_D_ERROR, "ERROR: Ptr->Union.DataBlock(0x%lx) > (MAX_ADDRESS - (UINTN)Ptr->Length(0x%lx))\n", Ptr->Union.DataBlock, Ptr->Length));
- return NULL;
- }
-
- //
- //To enhance the reliability of check-up, the first capsule's header is checked here.
- //More reliabilities check-up will do later.
- //
- if (CapsuleSize == 0) {
- //
- //Move to the first capsule to check its header.
- //
- CapsuleHeader = (EFI_CAPSULE_HEADER*)((UINTN)Ptr->Union.DataBlock);
- //
- // Sanity check
- //
- if (Ptr->Length < sizeof(EFI_CAPSULE_HEADER)) {
- DEBUG ((EFI_D_ERROR, "ERROR: Ptr->Length(0x%lx) < sizeof(EFI_CAPSULE_HEADER)\n", Ptr->Length));
- return NULL;
- }
- //
- // Make sure HeaderSize field is valid
- //
- if (CapsuleHeader->HeaderSize > CapsuleHeader->CapsuleImageSize) {
- DEBUG ((EFI_D_ERROR, "ERROR: CapsuleHeader->HeaderSize(0x%x) > CapsuleHeader->CapsuleImageSize(0x%x)\n", CapsuleHeader->HeaderSize, CapsuleHeader->CapsuleImageSize));
- return NULL;
- }
- if (IsCapsuleCorrupted (CapsuleHeader)) {
- return NULL;
- }
- CapsuleCount ++;
- CapsuleSize = CapsuleHeader->CapsuleImageSize;
- }
-
- if (CapsuleSize >= Ptr->Length) {
- CapsuleSize = CapsuleSize - Ptr->Length;
- } else {
- DEBUG ((EFI_D_ERROR, "ERROR: CapsuleSize(0x%lx) < Ptr->Length(0x%lx)\n", CapsuleSize, Ptr->Length));
- //
- // Sanity check
- //
- return NULL;
- }
-
- //
- // Move to next BLOCK descriptor
- //
- Ptr++;
- DEBUG ((EFI_D_INFO, "Ptr(B) - 0x%x\n", Ptr));
- DEBUG ((EFI_D_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));
- DEBUG ((EFI_D_INFO, "Ptr->Union - 0x%x\n", Ptr->Union.ContinuationPointer));
- }
- }
-
- if (CapsuleCount == 0) {
- //
- // No any capsule is found in BlockList
- //
- DEBUG ((EFI_D_ERROR, "ERROR: CapsuleCount(0x%x) == 0\n", CapsuleCount));
- return NULL;
- }
-
- if (CapsuleSize != 0) {
- //
- // Capsule data is incomplete.
- //
- DEBUG ((EFI_D_ERROR, "ERROR: CapsuleSize(0x%lx) != 0\n", CapsuleSize));
- return NULL;
- }
-
- return Ptr;
-}
-
-/**
- The capsule block descriptors may be fragmented and spread all over memory.
- To simplify the coalescing of capsule blocks, first coalesce all the
- capsule block descriptors low in memory.
-
- The descriptors passed in can be fragmented throughout memory. Here
- they are relocated into memory to turn them into a contiguous (null
- terminated) array.
-
- @param PeiServices pointer to PEI services table
- @param BlockList pointer to the capsule block descriptors
- @param NumDescriptors number of capsule data block descriptors, whose Length is non-zero.
- @param MemBase base of system memory in which we can work
- @param MemSize size of the system memory pointed to by MemBase
-
- @retval NULL could not relocate the descriptors
- @retval Pointer to the base of the successfully-relocated block descriptors.
-
-**/
-EFI_CAPSULE_BLOCK_DESCRIPTOR *
-RelocateBlockDescriptors (
- IN EFI_PEI_SERVICES **PeiServices,
- IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList,
- IN UINTN NumDescriptors,
- IN UINT8 *MemBase,
- IN UINTN MemSize
- )
-{
- EFI_CAPSULE_BLOCK_DESCRIPTOR *NewBlockList;
- EFI_CAPSULE_BLOCK_DESCRIPTOR *CurrBlockDescHead;
- EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockDesc;
- EFI_CAPSULE_BLOCK_DESCRIPTOR *PrevBlockDescTail;
- UINTN BufferSize;
- UINT8 *RelocBuffer;
- UINTN BlockListSize;
-
- //
- // Get the info on the blocks and descriptors. Since we're going to move
- // the descriptors low in memory, adjust the base/size values accordingly here.
- // NumDescriptors is the number of legit data descriptors, so add one for
- // a terminator. (Already done by caller, no check is needed.)
- //
-
- BufferSize = NumDescriptors * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
- NewBlockList = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) MemBase;
- if (MemSize < BufferSize) {
- return NULL;
- }
-
- MemSize -= BufferSize;
- MemBase += BufferSize;
- //
- // Go through all the blocks and make sure none are in the way
- //
- TempBlockDesc = BlockList;
- while (TempBlockDesc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL) {
- if (TempBlockDesc->Length == 0) {
- //
- // Next block of descriptors
- //
- TempBlockDesc = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) TempBlockDesc->Union.ContinuationPointer;
- } else {
- //
- // If the capsule data pointed to by this descriptor is in the way,
- // move it.
- //
- if (IsOverlapped (
- (UINT8 *) NewBlockList,
- BufferSize,
- (UINT8 *) (UINTN) TempBlockDesc->Union.DataBlock,
- (UINTN) TempBlockDesc->Length
- )) {
- //
- // Relocate the block
- //
- RelocBuffer = FindFreeMem (BlockList, MemBase, MemSize, (UINTN) TempBlockDesc->Length);
- if (RelocBuffer == NULL) {
- return NULL;
- }
-
- CopyMem ((VOID *) RelocBuffer, (VOID *) (UINTN) TempBlockDesc->Union.DataBlock, (UINTN) TempBlockDesc->Length);
- DEBUG ((EFI_D_INFO, "Capsule relocate descriptors from/to/size 0x%lX 0x%lX 0x%lX\n", TempBlockDesc->Union.DataBlock, (UINT64)(UINTN)RelocBuffer, TempBlockDesc->Length));
- TempBlockDesc->Union.DataBlock = (EFI_PHYSICAL_ADDRESS) (UINTN) RelocBuffer;
- }
- TempBlockDesc++;
- }
- }
- //
- // Now go through all the block descriptors to make sure that they're not
- // in the memory region we want to copy them to.
- //
- CurrBlockDescHead = BlockList;
- PrevBlockDescTail = NULL;
- while ((CurrBlockDescHead != NULL) && (CurrBlockDescHead->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
- //
- // Get the size of this list then see if it overlaps our low region
- //
- TempBlockDesc = CurrBlockDescHead;
- BlockListSize = sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
- while (TempBlockDesc->Length != 0) {
- BlockListSize += sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
- TempBlockDesc++;
- }
-
- if (IsOverlapped (
- (UINT8 *) NewBlockList,
- BufferSize,
- (UINT8 *) CurrBlockDescHead,
- BlockListSize
- )) {
- //
- // Overlaps, so move it out of the way
- //
- RelocBuffer = FindFreeMem (BlockList, MemBase, MemSize, BlockListSize);
- if (RelocBuffer == NULL) {
- return NULL;
- }
- CopyMem ((VOID *) RelocBuffer, (VOID *) CurrBlockDescHead, BlockListSize);
- DEBUG ((EFI_D_INFO, "Capsule reloc descriptor block #2\n"));
- //
- // Point the previous block's next point to this copied version. If
- // the tail pointer is null, then this is the first descriptor block.
- //
- if (PrevBlockDescTail == NULL) {
- BlockList = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) RelocBuffer;
- } else {
- PrevBlockDescTail->Union.DataBlock = (EFI_PHYSICAL_ADDRESS) (UINTN) RelocBuffer;
- }
- }
- //
- // Save our new tail and jump to the next block list
- //
- PrevBlockDescTail = TempBlockDesc;
- CurrBlockDescHead = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) TempBlockDesc->Union.ContinuationPointer;
- }
- //
- // Cleared out low memory. Now copy the descriptors down there.
- //
- TempBlockDesc = BlockList;
- CurrBlockDescHead = NewBlockList;
- while ((TempBlockDesc != NULL) && (TempBlockDesc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
- if (TempBlockDesc->Length != 0) {
- CurrBlockDescHead->Union.DataBlock = TempBlockDesc->Union.DataBlock;
- CurrBlockDescHead->Length = TempBlockDesc->Length;
- CurrBlockDescHead++;
- TempBlockDesc++;
- } else {
- TempBlockDesc = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) TempBlockDesc->Union.ContinuationPointer;
- }
- }
- //
- // Null terminate
- //
- CurrBlockDescHead->Union.ContinuationPointer = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;
- CurrBlockDescHead->Length = 0;
- return NewBlockList;
-}
-
-/**
- Determine if two buffers overlap in memory.
-
- @param Buff1 pointer to first buffer
- @param Size1 size of Buff1
- @param Buff2 pointer to second buffer
- @param Size2 size of Buff2
-
- @retval TRUE Buffers overlap in memory.
- @retval FALSE Buffer doesn't overlap.
-
-**/
-BOOLEAN
-IsOverlapped (
- UINT8 *Buff1,
- UINTN Size1,
- UINT8 *Buff2,
- UINTN Size2
- )
-{
- //
- // If buff1's end is less than the start of buff2, then it's ok.
- // Also, if buff1's start is beyond buff2's end, then it's ok.
- //
- if (((Buff1 + Size1) <= Buff2) || (Buff1 >= (Buff2 + Size2))) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- Given a pointer to a capsule block descriptor, traverse the list to figure
- out how many legitimate descriptors there are, and how big the capsule it
- refers to is.
-
- @param Desc Pointer to the capsule block descriptors
- @param NumDescriptors Optional pointer to where to return the number of capsule data descriptors, whose Length is non-zero.
- @param CapsuleSize Optional pointer to where to return the capsule image size
- @param CapsuleNumber Optional pointer to where to return the number of capsule
-
- @retval EFI_NOT_FOUND No descriptors containing data in the list
- @retval EFI_SUCCESS Return data is valid
-
-**/
-EFI_STATUS
-GetCapsuleInfo (
- IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Desc,
- IN OUT UINTN *NumDescriptors OPTIONAL,
- IN OUT UINTN *CapsuleSize OPTIONAL,
- IN OUT UINTN *CapsuleNumber OPTIONAL
- )
-{
- UINTN Count;
- UINTN Size;
- UINTN Number;
- UINTN ThisCapsuleImageSize;
- EFI_CAPSULE_HEADER *CapsuleHeader;
-
- DEBUG ((EFI_D_INFO, "GetCapsuleInfo enter\n"));
-
- ASSERT (Desc != NULL);
-
- Count = 0;
- Size = 0;
- Number = 0;
- ThisCapsuleImageSize = 0;
-
- while (Desc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL) {
- if (Desc->Length == 0) {
- //
- // Descriptor points to another list of block descriptors somewhere
- //
- Desc = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) Desc->Union.ContinuationPointer;
- } else {
- //
- // Sanity Check
- // It is needed, because ValidateCapsuleIntegrity() only validate one individual capsule Size.
- // While here we need check all capsules size.
- //
- if (Desc->Length >= (MAX_ADDRESS - Size)) {
- DEBUG ((EFI_D_ERROR, "ERROR: Desc->Length(0x%lx) >= (MAX_ADDRESS - Size(0x%x))\n", Desc->Length, Size));
- return EFI_OUT_OF_RESOURCES;
- }
- Size += (UINTN) Desc->Length;
- Count++;
-
- //
- // See if this is first capsule's header
- //
- if (ThisCapsuleImageSize == 0) {
- CapsuleHeader = (EFI_CAPSULE_HEADER*)((UINTN)Desc->Union.DataBlock);
- //
- // This has been checked in ValidateCapsuleIntegrity()
- //
- Number ++;
- ThisCapsuleImageSize = CapsuleHeader->CapsuleImageSize;
- }
-
- //
- // This has been checked in ValidateCapsuleIntegrity()
- //
- ASSERT (ThisCapsuleImageSize >= Desc->Length);
- ThisCapsuleImageSize = (UINTN)(ThisCapsuleImageSize - Desc->Length);
-
- //
- // Move to next
- //
- Desc++;
- }
- }
- //
- // If no descriptors, then fail
- //
- if (Count == 0) {
- DEBUG ((EFI_D_ERROR, "ERROR: Count == 0\n"));
- return EFI_NOT_FOUND;
- }
-
- //
- // checked in ValidateCapsuleIntegrity()
- //
- ASSERT (ThisCapsuleImageSize == 0);
-
- if (NumDescriptors != NULL) {
- *NumDescriptors = Count;
- }
-
- if (CapsuleSize != NULL) {
- *CapsuleSize = Size;
- }
-
- if (CapsuleNumber != NULL) {
- *CapsuleNumber = Number;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Check every capsule header.
-
- @param CapsuleHeader The pointer to EFI_CAPSULE_HEADER
-
- @retval FALSE Capsule is OK
- @retval TRUE Capsule is corrupted
-
-**/
-BOOLEAN
-IsCapsuleCorrupted (
- IN EFI_CAPSULE_HEADER *CapsuleHeader
- )
-{
- //
- //A capsule to be updated across a system reset should contain CAPSULE_FLAGS_PERSIST_ACROSS_RESET.
- //
- if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) == 0) {
- return TRUE;
- }
- //
- //Make sure the flags combination is supported by the platform.
- //
- if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {
- return TRUE;
- }
- if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_INITIATE_RESET)) == CAPSULE_FLAGS_INITIATE_RESET) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- Try to verify the integrity of a capsule test pattern before the
- capsule gets coalesced. This can be useful in narrowing down
- where capsule data corruption occurs.
-
- The test pattern mode fills in memory with a counting UINT32 value.
- If the capsule is not divided up in a multiple of 4-byte blocks, then
- things get messy doing the check. Therefore there are some cases
- here where we just give up and skip the pre-coalesce check.
-
- @param PeiServices PEI services table
- @param Desc Pointer to capsule descriptors
-**/
-VOID
-CapsuleTestPatternPreCoalesce (
- IN EFI_PEI_SERVICES **PeiServices,
- IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Desc
- )
-{
- UINT32 *TestPtr;
- UINT32 TestCounter;
- UINT32 TestSize;
-
- DEBUG ((EFI_D_INFO, "CapsuleTestPatternPreCoalesce\n"));
-
- //
- // Find first data descriptor
- //
- while ((Desc->Length == 0) && (Desc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
- Desc = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) Desc->Union.ContinuationPointer;
- }
-
- if (Desc->Union.ContinuationPointer == 0) {
- return ;
- }
- //
- // First one better be long enough to at least hold the test signature
- //
- if (Desc->Length < sizeof (UINT32)) {
- DEBUG ((EFI_D_INFO, "Capsule test pattern pre-coalesce punted #1\n"));
- return ;
- }
-
- TestPtr = (UINT32 *) (UINTN) Desc->Union.DataBlock;
- //
- // 0x54534554 "TEST"
- //
- if (*TestPtr != 0x54534554) {
- return ;
- }
-
- TestCounter = 0;
- TestSize = (UINT32) Desc->Length - 2 * sizeof (UINT32);
- //
- // Skip over the signature and the size fields in the pattern data header
- //
- TestPtr += 2;
- while (1) {
- if ((TestSize & 0x03) != 0) {
- DEBUG ((EFI_D_INFO, "Capsule test pattern pre-coalesce punted #2\n"));
- return ;
- }
-
- while (TestSize > 0) {
- if (*TestPtr != TestCounter) {
- DEBUG ((EFI_D_INFO, "Capsule test pattern pre-coalesce failed data corruption check\n"));
- return ;
- }
-
- TestSize -= sizeof (UINT32);
- TestCounter++;
- TestPtr++;
- }
- Desc++;
- while ((Desc->Length == 0) && (Desc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
- Desc = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) Desc->Union.ContinuationPointer;
- }
-
- if (Desc->Union.ContinuationPointer == (EFI_PHYSICAL_ADDRESS) (UINTN) NULL) {
- return ;
- }
- TestSize = (UINT32) Desc->Length;
- TestPtr = (UINT32 *) (UINTN) Desc->Union.DataBlock;
- }
-}
-
-/**
- Checks for the presence of capsule descriptors.
- Get capsule descriptors from variable CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
-
- @param BlockListBuffer Pointer to the buffer of capsule descriptors variables
- @param BlockDescriptorList Pointer to the capsule descriptors list
-
- @retval EFI_SUCCESS a valid capsule is present
- @retval EFI_NOT_FOUND if a valid capsule is not present
-**/
-EFI_STATUS
-BuildCapsuleDescriptors (
- IN EFI_PHYSICAL_ADDRESS *BlockListBuffer,
- OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptorList
- )
-{
- UINTN Index;
- EFI_CAPSULE_BLOCK_DESCRIPTOR *LastBlock;
- EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlock;
- EFI_CAPSULE_BLOCK_DESCRIPTOR *HeadBlock;
-
- DEBUG ((EFI_D_INFO, "BuildCapsuleDescriptors enter\n"));
-
- LastBlock = NULL;
- HeadBlock = NULL;
- TempBlock = NULL;
- Index = 0;
-
- while (BlockListBuffer[Index] != 0) {
- //
- // Test integrity of descriptors.
- //
- if (BlockListBuffer[Index] < MAX_ADDRESS) {
- TempBlock = ValidateCapsuleIntegrity ((EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)BlockListBuffer[Index]);
- if (TempBlock != NULL) {
- if (LastBlock == NULL) {
- LastBlock = TempBlock;
-
- //
- // Return the base of the block descriptors
- //
- HeadBlock = (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)BlockListBuffer[Index];
- } else {
- //
- // Combine the different BlockList into single BlockList.
- //
- LastBlock->Union.DataBlock = (EFI_PHYSICAL_ADDRESS)(UINTN)BlockListBuffer[Index];
- LastBlock->Length = 0;
- LastBlock = TempBlock;
- }
- }
- } else {
- DEBUG ((EFI_D_ERROR, "ERROR: BlockListBuffer[Index](0x%lx) < MAX_ADDRESS\n", BlockListBuffer[Index]));
- }
- Index ++;
- }
-
- if (HeadBlock != NULL) {
- *BlockDescriptorList = HeadBlock;
- return EFI_SUCCESS;
- }
- return EFI_NOT_FOUND;
-}
-
-/**
- The function to coalesce a fragmented capsule in memory.
-
- Memory Map for coalesced capsule:
- MemBase + ---->+---------------------------+<-----------+
- MemSize | ------------------------- | |
- | | Capsule [Num-1] | | |
- | ------------------------- | |
- | | ................ | | |
- | ------------------------- | |
- | | Capsule [1] | | |
- | ------------------------- | |
- | | Capsule [0] | | |
- | ------------------------- | |
- | Capsule Image | |
-CapsuleImageBase-->+---------------------------+
- | ------------------------- | |
- | | CapsuleOffset[Num-1] | | |
- | ------------------------- | |
- | | ................ | | CapsuleSize
- | ------------------------- | |
- | | CapsuleOffset[1] | | |
- | ------------------------- | |
- | | CapsuleOffset[0] | | |
- |---------------------------| |
- | | CapsuleNumber | | |
- | ------------------------- | |
- | | CapsuleAllImageSize | | |
- | ------------------------- | |
- | PrivateData | |
- DestPtr ---->+---------------------------+<-----------+
- | | |
- | FreeMem | FreeMemSize
- | | |
- FreeMemBase --->+---------------------------+<-----------+
- | Terminator |
- +---------------------------+
- | BlockDescriptor n |
- +---------------------------+
- | ................. |
- +---------------------------+
- | BlockDescriptor 1 |
- +---------------------------+
- | BlockDescriptor 0 |
- +---------------------------+
- | PrivateDataDesc 0 |
- MemBase ---->+---------------------------+<----- BlockList
-
- Caution: This function may receive untrusted input.
- The capsule data is external input, so this routine will do basic validation before
- coalesce capsule data into memory.
-
- @param PeiServices General purpose services available to every PEIM.
- @param BlockListBuffer Point to the buffer of Capsule Descriptor Variables.
- @param MemoryBase Pointer to the base of a block of memory that we can walk
- all over while trying to coalesce our buffers.
- On output, this variable will hold the base address of
- a coalesced capsule.
- @param MemorySize Size of the memory region pointed to by MemoryBase.
- On output, this variable will contain the size of the
- coalesced capsule.
-
- @retval EFI_NOT_FOUND If we could not find the capsule descriptors.
-
- @retval EFI_BUFFER_TOO_SMALL
- If we could not coalesce the capsule in the memory
- region provided to us.
-
- @retval EFI_SUCCESS Processed the capsule successfully.
-**/
-EFI_STATUS
-EFIAPI
-CapsuleDataCoalesce (
- IN EFI_PEI_SERVICES **PeiServices,
- IN EFI_PHYSICAL_ADDRESS *BlockListBuffer,
- IN OUT VOID **MemoryBase,
- IN OUT UINTN *MemorySize
- )
-{
- VOID *NewCapsuleBase;
- VOID *CapsuleImageBase;
- UINTN CapsuleIndex;
- UINT8 *FreeMemBase;
- UINT8 *DestPtr;
- UINTN DestLength;
- UINT8 *RelocPtr;
- UINTN CapsuleTimes;
- UINT64 SizeLeft;
- UINT64 CapsuleImageSize;
- UINTN CapsuleSize;
- UINTN CapsuleNumber;
- UINTN DescriptorsSize;
- UINTN FreeMemSize;
- UINTN NumDescriptors;
- BOOLEAN CapsuleBeginFlag;
- EFI_STATUS Status;
- EFI_CAPSULE_HEADER *CapsuleHeader;
- EFI_CAPSULE_PEIM_PRIVATE_DATA PrivateData;
- EFI_CAPSULE_PEIM_PRIVATE_DATA *PrivateDataPtr;
- EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList;
- EFI_CAPSULE_BLOCK_DESCRIPTOR *CurrentBlockDesc;
- EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockDesc;
- EFI_CAPSULE_BLOCK_DESCRIPTOR PrivateDataDesc[2];
-
- DEBUG ((EFI_D_INFO, "CapsuleDataCoalesce enter\n"));
-
- CapsuleIndex = 0;
- SizeLeft = 0;
- CapsuleTimes = 0;
- CapsuleImageSize = 0;
- PrivateDataPtr = NULL;
- CapsuleHeader = NULL;
- CapsuleBeginFlag = TRUE;
- CapsuleSize = 0;
- NumDescriptors = 0;
-
- //
- // Build capsule descriptors list
- //
- Status = BuildCapsuleDescriptors (BlockListBuffer, &BlockList);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- DEBUG_CODE (
- CapsuleTestPatternPreCoalesce (PeiServices, BlockList);
- );
-
- //
- // Get the size of our descriptors and the capsule size. GetCapsuleInfo()
- // returns the number of descriptors that actually point to data, so add
- // one for a terminator. Do that below.
- //
- Status = GetCapsuleInfo (BlockList, &NumDescriptors, &CapsuleSize, &CapsuleNumber);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- DEBUG ((EFI_D_INFO, "CapsuleSize - 0x%x\n", CapsuleSize));
- DEBUG ((EFI_D_INFO, "CapsuleNumber - 0x%x\n", CapsuleNumber));
- DEBUG ((EFI_D_INFO, "NumDescriptors - 0x%x\n", NumDescriptors));
- if ((CapsuleSize == 0) || (NumDescriptors == 0) || (CapsuleNumber == 0)) {
- return EFI_NOT_FOUND;
- }
-
- if (CapsuleNumber - 1 >= (MAX_ADDRESS - (sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) + sizeof(UINT64))) / sizeof(UINT64)) {
- DEBUG ((EFI_D_ERROR, "ERROR: CapsuleNumber - 0x%x\n", CapsuleNumber));
- return EFI_BUFFER_TOO_SMALL;
- }
-
- //
- // Initialize our local copy of private data. When we're done, we'll create a
- // descriptor for it as well so that it can be put into free memory without
- // trashing anything.
- //
- PrivateData.Signature = EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE;
- PrivateData.CapsuleAllImageSize = (UINT64) CapsuleSize;
- PrivateData.CapsuleNumber = (UINT64) CapsuleNumber;
- PrivateData.CapsuleOffset[0] = 0;
- //
- // NOTE: Only data in sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) is valid, CapsuleOffset field is unitialized at this moment.
- // The code sets partial length here for Descriptor.Length check, but later it will use full length to reserve those PrivateData region.
- //
- PrivateDataDesc[0].Union.DataBlock = (EFI_PHYSICAL_ADDRESS) (UINTN) &PrivateData;
- PrivateDataDesc[0].Length = sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA);
- PrivateDataDesc[1].Union.DataBlock = (EFI_PHYSICAL_ADDRESS) (UINTN) BlockList;
- PrivateDataDesc[1].Length = 0;
- //
- // Add PrivateDataDesc[0] in beginning beginning, as it is new descriptor. PrivateDataDesc[1] is NOT needed.
- // In addition, one NULL terminator is added in the end. See RelocateBlockDescriptors().
- //
- NumDescriptors += 2;
- //
- // Sandity check
- //
- if (CapsuleSize >= (MAX_ADDRESS - (sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64) + sizeof(UINT64)))) {
- DEBUG ((EFI_D_ERROR, "ERROR: CapsuleSize - 0x%x\n", CapsuleSize));
- return EFI_BUFFER_TOO_SMALL;
- }
- //
- // Need add sizeof(UINT64) for PrivateData alignment
- //
- CapsuleSize += sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64) + sizeof(UINT64);
- BlockList = PrivateDataDesc;
- //
- // Sandity check
- //
- if (NumDescriptors >= (MAX_ADDRESS / sizeof(EFI_CAPSULE_BLOCK_DESCRIPTOR))) {
- DEBUG ((EFI_D_ERROR, "ERROR: NumDescriptors - 0x%x\n", NumDescriptors));
- return EFI_BUFFER_TOO_SMALL;
- }
- DescriptorsSize = NumDescriptors * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
- //
- // Sandity check
- //
- if (DescriptorsSize >= (MAX_ADDRESS - CapsuleSize)) {
- DEBUG ((EFI_D_ERROR, "ERROR: DescriptorsSize - 0x%lx, CapsuleSize - 0x%lx\n", (UINT64)DescriptorsSize, (UINT64)CapsuleSize));
- return EFI_BUFFER_TOO_SMALL;
- }
-
- //
- // Don't go below some min address. If the base is below it,
- // then move it up and adjust the size accordingly.
- //
- DEBUG ((EFI_D_INFO, "Capsule Memory range from 0x%8X to 0x%8X\n", (UINTN) *MemoryBase, (UINTN)*MemoryBase + *MemorySize));
- if ((UINTN)*MemoryBase < (UINTN) MIN_COALESCE_ADDR) {
- if (((UINTN)*MemoryBase + *MemorySize) < (UINTN) MIN_COALESCE_ADDR) {
- DEBUG ((EFI_D_ERROR, "ERROR: *MemoryBase + *MemorySize - 0x%x\n", (UINTN)*MemoryBase + *MemorySize));
- return EFI_BUFFER_TOO_SMALL;
- } else {
- *MemorySize = *MemorySize - ((UINTN) MIN_COALESCE_ADDR - (UINTN) *MemoryBase);
- *MemoryBase = (VOID *) (UINTN) MIN_COALESCE_ADDR;
- }
- }
-
- if (*MemorySize <= (CapsuleSize + DescriptorsSize)) {
- DEBUG ((EFI_D_ERROR, "ERROR: CapsuleSize + DescriptorsSize - 0x%x\n", CapsuleSize + DescriptorsSize));
- return EFI_BUFFER_TOO_SMALL;
- }
-
- FreeMemBase = *MemoryBase;
- FreeMemSize = *MemorySize;
- DEBUG ((EFI_D_INFO, "Capsule Free Memory from 0x%8X to 0x%8X\n", (UINTN) FreeMemBase, (UINTN) FreeMemBase + FreeMemSize));
-
- //
- // Relocate all the block descriptors to low memory to make further
- // processing easier.
- //
- BlockList = RelocateBlockDescriptors (PeiServices, BlockList, NumDescriptors, FreeMemBase, FreeMemSize);
- if (BlockList == NULL) {
- //
- // Not enough room to relocate the descriptors
- //
- return EFI_BUFFER_TOO_SMALL;
- }
-
- //
- // Take the top of memory for the capsule. UINT64 align up.
- //
- DestPtr = FreeMemBase + FreeMemSize - CapsuleSize;
- DestPtr = (UINT8 *) (((UINTN)DestPtr + sizeof (UINT64) - 1) & ~(sizeof (UINT64) - 1));
- FreeMemBase = (UINT8 *) BlockList + DescriptorsSize;
- FreeMemSize = (UINTN) DestPtr - (UINTN) FreeMemBase;
- NewCapsuleBase = (VOID *) DestPtr;
- CapsuleImageBase = (UINT8 *)NewCapsuleBase + sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64);
-
- PrivateDataPtr = (EFI_CAPSULE_PEIM_PRIVATE_DATA *) NewCapsuleBase;
-
- //
- // Move all the blocks to the top (high) of memory.
- // Relocate all the obstructing blocks. Note that the block descriptors
- // were coalesced when they were relocated, so we can just ++ the pointer.
- //
- CurrentBlockDesc = BlockList;
- while ((CurrentBlockDesc->Length != 0) || (CurrentBlockDesc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
- if (CapsuleTimes == 0) {
- //
- // The first entry is the block descriptor for EFI_CAPSULE_PEIM_PRIVATE_DATA.
- // CapsuleOffset field is uninitialized at this time. No need copy it, but need to reserve for future use.
- //
- ASSERT (CurrentBlockDesc->Union.DataBlock == (UINT64)(UINTN)&PrivateData);
- DestLength = sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64);
- } else {
- DestLength = (UINTN)CurrentBlockDesc->Length;
- }
- //
- // See if any of the remaining capsule blocks are in the way
- //
- TempBlockDesc = CurrentBlockDesc;
- while (TempBlockDesc->Length != 0) {
- //
- // Is this block in the way of where we want to copy the current descriptor to?
- //
- if (IsOverlapped (
- (UINT8 *) DestPtr,
- (UINTN) DestLength,
- (UINT8 *) (UINTN) TempBlockDesc->Union.DataBlock,
- (UINTN) TempBlockDesc->Length
- )) {
- //
- // Relocate the block
- //
- RelocPtr = FindFreeMem (BlockList, FreeMemBase, FreeMemSize, (UINTN) TempBlockDesc->Length);
- if (RelocPtr == NULL) {
- return EFI_BUFFER_TOO_SMALL;
- }
-
- CopyMem ((VOID *) RelocPtr, (VOID *) (UINTN) TempBlockDesc->Union.DataBlock, (UINTN) TempBlockDesc->Length);
- DEBUG ((EFI_D_INFO, "Capsule reloc data block from 0x%8X to 0x%8X with size 0x%8X\n",
- (UINTN) TempBlockDesc->Union.DataBlock, (UINTN) RelocPtr, (UINTN) TempBlockDesc->Length));
-
- TempBlockDesc->Union.DataBlock = (EFI_PHYSICAL_ADDRESS) (UINTN) RelocPtr;
- }
- //
- // Next descriptor
- //
- TempBlockDesc++;
- }
- //
- // Ok, we made it through. Copy the block.
- // we just support greping one capsule from the lists of block descs list.
- //
- CapsuleTimes ++;
- //
- //Skip the first block descriptor that filled with EFI_CAPSULE_PEIM_PRIVATE_DATA
- //
- if (CapsuleTimes > 1) {
- //
- //For every capsule entry point, check its header to determine whether to relocate it.
- //If it is invalid, skip it and move on to the next capsule. If it is valid, relocate it.
- //
- if (CapsuleBeginFlag) {
- CapsuleBeginFlag = FALSE;
- CapsuleHeader = (EFI_CAPSULE_HEADER*)(UINTN)CurrentBlockDesc->Union.DataBlock;
- SizeLeft = CapsuleHeader->CapsuleImageSize;
-
- //
- // No more check here is needed, because IsCapsuleCorrupted() already in ValidateCapsuleIntegrity()
- //
- ASSERT (CapsuleIndex < CapsuleNumber);
-
- //
- // Relocate this capsule
- //
- CapsuleImageSize += SizeLeft;
- //
- // Cache the begin offset of this capsule
- //
- ASSERT (PrivateDataPtr->Signature == EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE);
- ASSERT ((UINTN)DestPtr >= (UINTN)CapsuleImageBase);
- PrivateDataPtr->CapsuleOffset[CapsuleIndex++] = (UINT64)((UINTN)DestPtr - (UINTN)CapsuleImageBase);
- }
-
- //
- // Below ASSERT is checked in ValidateCapsuleIntegrity()
- //
- ASSERT (CurrentBlockDesc->Length <= SizeLeft);
-
- CopyMem ((VOID *) DestPtr, (VOID *) (UINTN) (CurrentBlockDesc->Union.DataBlock), (UINTN)CurrentBlockDesc->Length);
- DEBUG ((EFI_D_INFO, "Capsule coalesce block no.0x%lX from 0x%lX to 0x%lX with size 0x%lX\n",(UINT64)CapsuleTimes,
- CurrentBlockDesc->Union.DataBlock, (UINT64)(UINTN)DestPtr, CurrentBlockDesc->Length));
- DestPtr += CurrentBlockDesc->Length;
- SizeLeft -= CurrentBlockDesc->Length;
-
- if (SizeLeft == 0) {
- //
- //Here is the end of the current capsule image.
- //
- CapsuleBeginFlag = TRUE;
- }
- } else {
- //
- // The first entry is the block descriptor for EFI_CAPSULE_PEIM_PRIVATE_DATA.
- // CapsuleOffset field is uninitialized at this time. No need copy it, but need to reserve for future use.
- //
- ASSERT (CurrentBlockDesc->Length == sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA));
- ASSERT ((UINTN)DestPtr == (UINTN)NewCapsuleBase);
- CopyMem ((VOID *) DestPtr, (VOID *) (UINTN) CurrentBlockDesc->Union.DataBlock, (UINTN) CurrentBlockDesc->Length);
- DestPtr += sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64);
- }
- //
- //Walk through the block descriptor list.
- //
- CurrentBlockDesc++;
- }
- //
- // We return the base of memory we want reserved, and the size.
- // The memory peim should handle it appropriately from there.
- //
- *MemorySize = (UINTN) CapsuleSize;
- *MemoryBase = (VOID *) NewCapsuleBase;
-
- ASSERT (PrivateDataPtr->Signature == EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE);
- ASSERT (PrivateDataPtr->CapsuleAllImageSize == CapsuleImageSize);
- ASSERT (PrivateDataPtr->CapsuleNumber == CapsuleIndex);
-
- return EFI_SUCCESS;
-}
diff --git a/MdeModulePkg/Universal/CapsulePei/Common/CommonHeader.h b/MdeModulePkg/Universal/CapsulePei/Common/CommonHeader.h
deleted file mode 100644
index 6210d2133e..0000000000
--- a/MdeModulePkg/Universal/CapsulePei/Common/CommonHeader.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/** @file
- Common header file.
-
-Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
-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.
-
-**/
-
-#ifndef _CAPSULE_COMMON_HEADER_
-#define _CAPSULE_COMMON_HEADER_
-
-//
-// 8 extra pages for PF handler.
-//
-#define EXTRA_PAGE_TABLE_PAGES 8
-
-//
-// This capsule PEIM puts its private data at the start of the
-// coalesced capsule. Here's the structure definition.
-//
-#define EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('C', 'a', 'p', 'P')
-
-#pragma pack(1)
-typedef struct {
- UINT64 Signature;
- UINT64 CapsuleAllImageSize;
- UINT64 CapsuleNumber;
- UINT64 CapsuleOffset[1];
-} EFI_CAPSULE_PEIM_PRIVATE_DATA;
-#pragma pack()
-
-#define CAPSULE_TEST_SIGNATURE SIGNATURE_32('T', 'E', 'S', 'T')
-
-#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)
-#pragma pack(1)
-typedef struct {
- EFI_PHYSICAL_ADDRESS EntryPoint;
- EFI_PHYSICAL_ADDRESS StackBufferBase;
- UINT64 StackBufferLength;
- EFI_PHYSICAL_ADDRESS JumpBuffer;
- EFI_PHYSICAL_ADDRESS BlockListAddr;
- EFI_PHYSICAL_ADDRESS MemoryBase64Ptr;
- EFI_PHYSICAL_ADDRESS MemorySize64Ptr;
- BOOLEAN Page1GSupport;
-} SWITCH_32_TO_64_CONTEXT;
-
-typedef struct {
- UINT16 ReturnCs;
- EFI_PHYSICAL_ADDRESS ReturnEntryPoint;
- UINT64 ReturnStatus;
- //
- // NOTICE:
- // Be careful about the Base field of IA32_DESCRIPTOR
- // that is UINTN type.
- // To extend new field for this structure, add it to
- // right before this Gdtr field.
- //
- IA32_DESCRIPTOR Gdtr;
-} SWITCH_64_TO_32_CONTEXT;
-#pragma pack()
-#endif
-
-/**
- The function to coalesce a fragmented capsule in memory.
-
- @param PeiServices General purpose services available to every PEIM.
- @param BlockListBuffer Point to the buffer of Capsule Descriptor Variables.
- @param MemoryBase Pointer to the base of a block of memory that we can walk
- all over while trying to coalesce our buffers.
- On output, this variable will hold the base address of
- a coalesced capsule.
- @param MemorySize Size of the memory region pointed to by MemoryBase.
- On output, this variable will contain the size of the
- coalesced capsule.
-
- @retval EFI_NOT_FOUND if we can't determine the boot mode
- if the boot mode is not flash-update
- if we could not find the capsule descriptors
-
- @retval EFI_BUFFER_TOO_SMALL
- if we could not coalesce the capsule in the memory
- region provided to us
-
- @retval EFI_SUCCESS if there's no capsule, or if we processed the
- capsule successfully.
-**/
-EFI_STATUS
-EFIAPI
-CapsuleDataCoalesce (
- IN EFI_PEI_SERVICES **PeiServices,
- IN IN EFI_PHYSICAL_ADDRESS *BlockListBuffer,
- IN OUT VOID **MemoryBase,
- IN OUT UINTN *MemorySize
- );
-
-#endif
diff --git a/MdeModulePkg/Universal/CapsulePei/UefiCapsule.c b/MdeModulePkg/Universal/CapsulePei/UefiCapsule.c
deleted file mode 100644
index 61fafc7fe0..0000000000
--- a/MdeModulePkg/Universal/CapsulePei/UefiCapsule.c
+++ /dev/null
@@ -1,1063 +0,0 @@
-/** @file
- Capsule update PEIM for UEFI2.0
-
-Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
-
-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.
-
-**/
-
-#include "Capsule.h"
-
-#ifdef MDE_CPU_IA32
-//
-// Global Descriptor Table (GDT)
-//
-GLOBAL_REMOVE_IF_UNREFERENCED IA32_SEGMENT_DESCRIPTOR mGdtEntries[] = {
-/* selector { Global Segment Descriptor } */
-/* 0x00 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //null descriptor
-/* 0x08 */ {{0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //linear data segment descriptor
-/* 0x10 */ {{0xffff, 0, 0, 0xf, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //linear code segment descriptor
-/* 0x18 */ {{0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system data segment descriptor
-/* 0x20 */ {{0xffff, 0, 0, 0xb, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system code segment descriptor
-/* 0x28 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //spare segment descriptor
-/* 0x30 */ {{0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system data segment descriptor
-/* 0x38 */ {{0xffff, 0, 0, 0xb, 1, 0, 1, 0xf, 0, 1, 0, 1, 0}}, //system code segment descriptor
-/* 0x40 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //spare segment descriptor
-};
-
-//
-// IA32 Gdt register
-//
-GLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR mGdt = {
- sizeof (mGdtEntries) - 1,
- (UINTN) mGdtEntries
- };
-
-/**
- The function will check if 1G page is supported.
-
- @retval TRUE 1G page is supported.
- @retval FALSE 1G page is not supported.
-
-**/
-BOOLEAN
-IsPage1GSupport (
- VOID
- )
-{
- UINT32 RegEax;
- UINT32 RegEdx;
- BOOLEAN Page1GSupport;
-
- Page1GSupport = FALSE;
- if (PcdGetBool(PcdUse1GPageTable)) {
- AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
- if (RegEax >= 0x80000001) {
- AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
- if ((RegEdx & BIT26) != 0) {
- Page1GSupport = TRUE;
- }
- }
- }
-
- return Page1GSupport;
-}
-
-/**
- Calculate the total size of page table.
-
- @param[in] Page1GSupport 1G page support or not.
-
- @return The size of page table.
-
-**/
-UINTN
-CalculatePageTableSize (
- IN BOOLEAN Page1GSupport
- )
-{
- UINTN ExtraPageTablePages;
- UINTN TotalPagesNum;
- UINT8 PhysicalAddressBits;
- UINT32 NumberOfPml4EntriesNeeded;
- UINT32 NumberOfPdpEntriesNeeded;
-
- //
- // Create 4G page table by default,
- // and let PF handler to handle > 4G request.
- //
- PhysicalAddressBits = 32;
- ExtraPageTablePages = EXTRA_PAGE_TABLE_PAGES;
-
- //
- // Calculate the table entries needed.
- //
- if (PhysicalAddressBits <= 39 ) {
- NumberOfPml4EntriesNeeded = 1;
- NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30));
- } else {
- NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39));
- NumberOfPdpEntriesNeeded = 512;
- }
-
- if (!Page1GSupport) {
- TotalPagesNum = (NumberOfPdpEntriesNeeded + 1) * NumberOfPml4EntriesNeeded + 1;
- } else {
- TotalPagesNum = NumberOfPml4EntriesNeeded + 1;
- }
- TotalPagesNum += ExtraPageTablePages;
-
- return EFI_PAGES_TO_SIZE (TotalPagesNum);
-}
-
-/**
- Allocates and fills in the Page Directory and Page Table Entries to
- establish a 4G page table.
-
- @param[in] PageTablesAddress The base address of page table.
- @param[in] Page1GSupport 1G page support or not.
-
-**/
-VOID
-Create4GPageTables (
- IN EFI_PHYSICAL_ADDRESS PageTablesAddress,
- IN BOOLEAN Page1GSupport
- )
-{
- UINT8 PhysicalAddressBits;
- EFI_PHYSICAL_ADDRESS PageAddress;
- UINTN IndexOfPml4Entries;
- UINTN IndexOfPdpEntries;
- UINTN IndexOfPageDirectoryEntries;
- UINT32 NumberOfPml4EntriesNeeded;
- UINT32 NumberOfPdpEntriesNeeded;
- PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
- PAGE_MAP_AND_DIRECTORY_POINTER *PageMap;
- PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;
- PAGE_TABLE_ENTRY *PageDirectoryEntry;
- UINTN BigPageAddress;
- PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry;
-
- //
- // Create 4G page table by default,
- // and let PF handler to handle > 4G request.
- //
- PhysicalAddressBits = 32;
-
- //
- // Calculate the table entries needed.
- //
- if (PhysicalAddressBits <= 39 ) {
- NumberOfPml4EntriesNeeded = 1;
- NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30));
- } else {
- NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39));
- NumberOfPdpEntriesNeeded = 512;
- }
-
- //
- // Pre-allocate big pages to avoid later allocations.
- //
- BigPageAddress = (UINTN) PageTablesAddress;
-
- //
- // By architecture only one PageMapLevel4 exists - so lets allocate storage for it.
- //
- PageMap = (VOID *) BigPageAddress;
- BigPageAddress += SIZE_4KB;
-
- PageMapLevel4Entry = PageMap;
- PageAddress = 0;
- for (IndexOfPml4Entries = 0; IndexOfPml4Entries < NumberOfPml4EntriesNeeded; IndexOfPml4Entries++, PageMapLevel4Entry++) {
- //
- // Each PML4 entry points to a page of Page Directory Pointer entires.
- // So lets allocate space for them and fill them in in the IndexOfPdpEntries loop.
- //
- PageDirectoryPointerEntry = (VOID *) BigPageAddress;
- BigPageAddress += SIZE_4KB;
-
- //
- // Make a PML4 Entry
- //
- PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry;
- PageMapLevel4Entry->Bits.ReadWrite = 1;
- PageMapLevel4Entry->Bits.Present = 1;
-
- if (Page1GSupport) {
- PageDirectory1GEntry = (VOID *) PageDirectoryPointerEntry;
-
- for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {
- //
- // Fill in the Page Directory entries
- //
- PageDirectory1GEntry->Uint64 = (UINT64)PageAddress;
- PageDirectory1GEntry->Bits.ReadWrite = 1;
- PageDirectory1GEntry->Bits.Present = 1;
- PageDirectory1GEntry->Bits.MustBe1 = 1;
- }
- } else {
- for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
- //
- // Each Directory Pointer entries points to a page of Page Directory entires.
- // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.
- //
- PageDirectoryEntry = (VOID *) BigPageAddress;
- BigPageAddress += SIZE_4KB;
-
- //
- // Fill in a Page Directory Pointer Entries
- //
- PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry;
- PageDirectoryPointerEntry->Bits.ReadWrite = 1;
- PageDirectoryPointerEntry->Bits.Present = 1;
-
- for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += SIZE_2MB) {
- //
- // Fill in the Page Directory entries
- //
- PageDirectoryEntry->Uint64 = (UINT64)PageAddress;
- PageDirectoryEntry->Bits.ReadWrite = 1;
- PageDirectoryEntry->Bits.Present = 1;
- PageDirectoryEntry->Bits.MustBe1 = 1;
- }
- }
-
- for (; IndexOfPdpEntries < 512; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
- ZeroMem (
- PageDirectoryPointerEntry,
- sizeof(PAGE_MAP_AND_DIRECTORY_POINTER)
- );
- }
- }
- }
-
- //
- // For the PML4 entries we are not using fill in a null entry.
- //
- for (; IndexOfPml4Entries < 512; IndexOfPml4Entries++, PageMapLevel4Entry++) {
- ZeroMem (
- PageMapLevel4Entry,
- sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)
- );
- }
-}
-
-/**
- Return function from long mode to 32-bit mode.
-
- @param EntrypointContext Context for mode switching
- @param ReturnContext Context for mode switching
-
-**/
-VOID
-ReturnFunction (
- SWITCH_32_TO_64_CONTEXT *EntrypointContext,
- SWITCH_64_TO_32_CONTEXT *ReturnContext
- )
-{
- //
- // Restore original GDT
- //
- AsmWriteGdtr (&ReturnContext->Gdtr);
-
- //
- // return to original caller
- //
- LongJump ((BASE_LIBRARY_JUMP_BUFFER *)(UINTN)EntrypointContext->JumpBuffer, 1);
-
- //
- // never be here
- //
- ASSERT (FALSE);
-}
-
-/**
- Thunk function from 32-bit protection mode to long mode.
-
- @param PageTableAddress Page table base address
- @param Context Context for mode switching
- @param ReturnContext Context for mode switching
-
- @retval EFI_SUCCESS Function successfully executed.
-
-**/
-EFI_STATUS
-Thunk32To64 (
- EFI_PHYSICAL_ADDRESS PageTableAddress,
- SWITCH_32_TO_64_CONTEXT *Context,
- SWITCH_64_TO_32_CONTEXT *ReturnContext
- )
-{
- UINTN SetJumpFlag;
- EFI_STATUS Status;
-
- //
- // Save return address, LongJump will return here then
- //
- SetJumpFlag = SetJump ((BASE_LIBRARY_JUMP_BUFFER *) (UINTN) Context->JumpBuffer);
-
- if (SetJumpFlag == 0) {
-
- //
- // Build 4G Page Tables.
- //
- Create4GPageTables (PageTableAddress, Context->Page1GSupport);
-
- //
- // Create 64-bit GDT
- //
- AsmWriteGdtr (&mGdt);
-
- //
- // Write CR3
- //
- AsmWriteCr3 ((UINTN) PageTableAddress);
-
- //
- // Disable interrupt of Debug timer, since the IDT table cannot work in long mode
- //
- SaveAndSetDebugTimerInterrupt (FALSE);
- //
- // Transfer to long mode
- //
- AsmEnablePaging64 (
- 0x38,
- (UINT64) Context->EntryPoint,
- (UINT64)(UINTN) Context,
- (UINT64)(UINTN) ReturnContext,
- Context->StackBufferBase + Context->StackBufferLength
- );
- }
-
- //
- // Convert to 32-bit Status and return
- //
- Status = EFI_SUCCESS;
- if ((UINTN) ReturnContext->ReturnStatus != 0) {
- Status = ENCODE_ERROR ((UINTN) ReturnContext->ReturnStatus);
- }
-
- return Status;
-}
-
-/**
- If in 32 bit protection mode, and coalesce image is of X64, switch to long mode.
-
- @param LongModeBuffer The context of long mode.
- @param CoalesceEntry Entry of coalesce image.
- @param BlockListAddr Address of block list.
- @param MemoryBase Base of memory range.
- @param MemorySize Size of memory range.
-
- @retval EFI_SUCCESS Successfully switched to long mode and execute coalesce.
- @retval Others Failed to execute coalesce in long mode.
-
-**/
-EFI_STATUS
-ModeSwitch (
- IN EFI_CAPSULE_LONG_MODE_BUFFER *LongModeBuffer,
- IN COALESCE_ENTRY CoalesceEntry,
- IN EFI_PHYSICAL_ADDRESS BlockListAddr,
- IN OUT VOID **MemoryBase,
- IN OUT UINTN *MemorySize
- )
-{
- EFI_STATUS Status;
- EFI_PHYSICAL_ADDRESS MemoryBase64;
- UINT64 MemorySize64;
- EFI_PHYSICAL_ADDRESS MemoryEnd64;
- SWITCH_32_TO_64_CONTEXT Context;
- SWITCH_64_TO_32_CONTEXT ReturnContext;
- BASE_LIBRARY_JUMP_BUFFER JumpBuffer;
- EFI_PHYSICAL_ADDRESS ReservedRangeBase;
- EFI_PHYSICAL_ADDRESS ReservedRangeEnd;
- BOOLEAN Page1GSupport;
-
- ZeroMem (&Context, sizeof (SWITCH_32_TO_64_CONTEXT));
- ZeroMem (&ReturnContext, sizeof (SWITCH_64_TO_32_CONTEXT));
-
- MemoryBase64 = (UINT64) (UINTN) *MemoryBase;
- MemorySize64 = (UINT64) (UINTN) *MemorySize;
- MemoryEnd64 = MemoryBase64 + MemorySize64;
-
- Page1GSupport = IsPage1GSupport ();
-
- //
- // Merge memory range reserved for stack and page table
- //
- if (LongModeBuffer->StackBaseAddress < LongModeBuffer->PageTableAddress) {
- ReservedRangeBase = LongModeBuffer->StackBaseAddress;
- ReservedRangeEnd = LongModeBuffer->PageTableAddress + CalculatePageTableSize (Page1GSupport);
- } else {
- ReservedRangeBase = LongModeBuffer->PageTableAddress;
- ReservedRangeEnd = LongModeBuffer->StackBaseAddress + LongModeBuffer->StackSize;
- }
-
- //
- // Check if memory range reserved is overlap with MemoryBase ~ MemoryBase + MemorySize.
- // If they are overlapped, get a larger range to process capsule data.
- //
- if (ReservedRangeBase <= MemoryBase64) {
- if (ReservedRangeEnd < MemoryEnd64) {
- MemoryBase64 = ReservedRangeEnd;
- } else {
- DEBUG ((EFI_D_ERROR, "Memory is not enough to process capsule!\n"));
- return EFI_OUT_OF_RESOURCES;
- }
- } else if (ReservedRangeBase < MemoryEnd64) {
- if (ReservedRangeEnd < MemoryEnd64 &&
- ReservedRangeBase - MemoryBase64 < MemoryEnd64 - ReservedRangeEnd) {
- MemoryBase64 = ReservedRangeEnd;
- } else {
- MemorySize64 = (UINT64)(UINTN)(ReservedRangeBase - MemoryBase64);
- }
- }
-
- //
- // Initialize context jumping to 64-bit enviroment
- //
- Context.JumpBuffer = (EFI_PHYSICAL_ADDRESS)(UINTN)&JumpBuffer;
- Context.StackBufferBase = LongModeBuffer->StackBaseAddress;
- Context.StackBufferLength = LongModeBuffer->StackSize;
- Context.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)CoalesceEntry;
- Context.BlockListAddr = BlockListAddr;
- Context.MemoryBase64Ptr = (EFI_PHYSICAL_ADDRESS)(UINTN)&MemoryBase64;
- Context.MemorySize64Ptr = (EFI_PHYSICAL_ADDRESS)(UINTN)&MemorySize64;
- Context.Page1GSupport = Page1GSupport;
-
- //
- // Prepare data for return back
- //
- ReturnContext.ReturnCs = 0x10;
- ReturnContext.ReturnEntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)ReturnFunction;
- //
- // Will save the return status of processing capsule
- //
- ReturnContext.ReturnStatus = 0;
-
- //
- // Save original GDT
- //
- AsmReadGdtr ((IA32_DESCRIPTOR *)&ReturnContext.Gdtr);
-
- Status = Thunk32To64 (LongModeBuffer->PageTableAddress, &Context, &ReturnContext);
-
- if (!EFI_ERROR (Status)) {
- *MemoryBase = (VOID *) (UINTN) MemoryBase64;
- *MemorySize = (UINTN) MemorySize64;
- }
-
- return Status;
-
-}
-
-/**
- Locates the coalesce image entry point, and detects its machine type.
-
- @param CoalesceImageEntryPoint Pointer to coalesce image entry point for output.
- @param CoalesceImageMachineType Pointer to machine type of coalesce image.
-
- @retval EFI_SUCCESS Coalesce image successfully located.
- @retval Others Failed to locate the coalesce image.
-
-**/
-EFI_STATUS
-FindCapsuleCoalesceImage (
- OUT EFI_PHYSICAL_ADDRESS *CoalesceImageEntryPoint,
- OUT UINT16 *CoalesceImageMachineType
- )
-{
- EFI_STATUS Status;
- UINTN Instance;
- EFI_PEI_LOAD_FILE_PPI *LoadFile;
- EFI_PEI_FV_HANDLE VolumeHandle;
- EFI_PEI_FILE_HANDLE FileHandle;
- EFI_PHYSICAL_ADDRESS CoalesceImageAddress;
- UINT64 CoalesceImageSize;
- UINT32 AuthenticationState;
-
- Instance = 0;
-
- while (TRUE) {
- Status = PeiServicesFfsFindNextVolume (Instance++, &VolumeHandle);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Status = PeiServicesFfsFindFileByName (PcdGetPtr(PcdCapsuleCoalesceFile), VolumeHandle, &FileHandle);
- if (!EFI_ERROR (Status)) {
- Status = PeiServicesLocatePpi (&gEfiPeiLoadFilePpiGuid, 0, NULL, (VOID **) &LoadFile);
- ASSERT_EFI_ERROR (Status);
-
- Status = LoadFile->LoadFile (
- LoadFile,
- FileHandle,
- &CoalesceImageAddress,
- &CoalesceImageSize,
- CoalesceImageEntryPoint,
- &AuthenticationState
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Unable to find PE32 section in CapsuleX64 image ffs %r!\n", Status));
- return Status;
- }
- *CoalesceImageMachineType = PeCoffLoaderGetMachineType ((VOID *) (UINTN) CoalesceImageAddress);
- break;
- } else {
- continue;
- }
- }
-
- return Status;
-}
-
-/**
- Gets the reserved long mode buffer.
-
- @param LongModeBuffer Pointer to the long mode buffer for output.
-
- @retval EFI_SUCCESS Long mode buffer successfully retrieved.
- @retval Others Variable storing long mode buffer not found.
-
-**/
-EFI_STATUS
-GetLongModeContext (
- OUT EFI_CAPSULE_LONG_MODE_BUFFER *LongModeBuffer
- )
-{
- EFI_STATUS Status;
- UINTN Size;
- EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;
-
- Status = PeiServicesLocatePpi (
- &gEfiPeiReadOnlyVariable2PpiGuid,
- 0,
- NULL,
- (VOID **) &PPIVariableServices
- );
- ASSERT_EFI_ERROR (Status);
-
- Size = sizeof (EFI_CAPSULE_LONG_MODE_BUFFER);
- Status = PPIVariableServices->GetVariable (
- PPIVariableServices,
- EFI_CAPSULE_LONG_MODE_BUFFER_NAME,
- &gEfiCapsuleVendorGuid,
- NULL,
- &Size,
- LongModeBuffer
- );
- if (EFI_ERROR (Status)) {
- DEBUG (( EFI_D_ERROR, "Error Get LongModeBuffer variable %r!\n", Status));
- }
- return Status;
-}
-#endif
-
-/**
- Checks for the presence of capsule descriptors.
- Get capsule descriptors from variable CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
- and save to DescriptorBuffer.
-
- @param DescriptorBuffer Pointer to the capsule descriptors
-
- @retval EFI_SUCCESS a valid capsule is present
- @retval EFI_NOT_FOUND if a valid capsule is not present
-**/
-EFI_STATUS
-GetCapsuleDescriptors (
- IN EFI_PHYSICAL_ADDRESS *DescriptorBuffer
- )
-{
- EFI_STATUS Status;
- UINTN Size;
- UINTN Index;
- UINTN TempIndex;
- UINTN ValidIndex;
- BOOLEAN Flag;
- CHAR16 CapsuleVarName[30];
- CHAR16 *TempVarName;
- EFI_PHYSICAL_ADDRESS CapsuleDataPtr64;
- EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;
-
- Index = 0;
- TempVarName = NULL;
- CapsuleVarName[0] = 0;
- ValidIndex = 0;
- CapsuleDataPtr64 = 0;
-
- Status = PeiServicesLocatePpi (
- &gEfiPeiReadOnlyVariable2PpiGuid,
- 0,
- NULL,
- (VOID **) &PPIVariableServices
- );
- if (Status == EFI_SUCCESS) {
- StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CHAR16), EFI_CAPSULE_VARIABLE_NAME);
- TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
- Size = sizeof (CapsuleDataPtr64);
- while (1) {
- if (Index == 0) {
- //
- // For the first Capsule Image
- //
- Status = PPIVariableServices->GetVariable (
- PPIVariableServices,
- CapsuleVarName,
- &gEfiCapsuleVendorGuid,
- NULL,
- &Size,
- (VOID *) &CapsuleDataPtr64
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Capsule -- capsule variable not set\n"));
- return EFI_NOT_FOUND;
- }
- //
- // We have a chicken/egg situation where the memory init code needs to
- // know the boot mode prior to initializing memory. For this case, our
- // validate function will fail. We can detect if this is the case if blocklist
- // pointer is null. In that case, return success since we know that the
- // variable is set.
- //
- if (DescriptorBuffer == NULL) {
- return EFI_SUCCESS;
- }
- } else {
- UnicodeValueToString (TempVarName, 0, Index, 0);
- Status = PPIVariableServices->GetVariable (
- PPIVariableServices,
- CapsuleVarName,
- &gEfiCapsuleVendorGuid,
- NULL,
- &Size,
- (VOID *) &CapsuleDataPtr64
- );
- if (EFI_ERROR (Status)) {
- break;
- }
-
- //
- // If this BlockList has been linked before, skip this variable
- //
- Flag = FALSE;
- for (TempIndex = 0; TempIndex < ValidIndex; TempIndex++) {
- if (DescriptorBuffer[TempIndex] == CapsuleDataPtr64) {
- Flag = TRUE;
- break;
- }
- }
- if (Flag) {
- Index ++;
- continue;
- }
- }
-
- //
- // Cache BlockList which has been processed
- //
- DescriptorBuffer[ValidIndex++] = CapsuleDataPtr64;
- Index ++;
- }
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Capsule PPI service to coalesce a fragmented capsule in memory.
-
- @param PeiServices General purpose services available to every PEIM.
- @param MemoryBase Pointer to the base of a block of memory that we can walk
- all over while trying to coalesce our buffers.
- On output, this variable will hold the base address of
- a coalesced capsule.
- @param MemorySize Size of the memory region pointed to by MemoryBase.
- On output, this variable will contain the size of the
- coalesced capsule.
-
- @retval EFI_NOT_FOUND if we can't determine the boot mode
- if the boot mode is not flash-update
- if we could not find the capsule descriptors
-
- @retval EFI_BUFFER_TOO_SMALL
- if we could not coalesce the capsule in the memory
- region provided to us
-
- @retval EFI_SUCCESS if there's no capsule, or if we processed the
- capsule successfully.
-**/
-EFI_STATUS
-EFIAPI
-CapsuleCoalesce (
- IN EFI_PEI_SERVICES **PeiServices,
- IN OUT VOID **MemoryBase,
- IN OUT UINTN *MemorySize
- )
-{
- UINTN Index;
- UINTN Size;
- UINTN VariableCount;
- CHAR16 CapsuleVarName[30];
- CHAR16 *TempVarName;
- EFI_PHYSICAL_ADDRESS CapsuleDataPtr64;
- EFI_STATUS Status;
- EFI_BOOT_MODE BootMode;
- EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;
- EFI_PHYSICAL_ADDRESS *VariableArrayAddress;
-#ifdef MDE_CPU_IA32
- UINT16 CoalesceImageMachineType;
- EFI_PHYSICAL_ADDRESS CoalesceImageEntryPoint;
- COALESCE_ENTRY CoalesceEntry;
- EFI_CAPSULE_LONG_MODE_BUFFER LongModeBuffer;
-#endif
-
- Index = 0;
- VariableCount = 0;
- CapsuleVarName[0] = 0;
- CapsuleDataPtr64 = 0;
-
- //
- // Someone should have already ascertained the boot mode. If it's not
- // capsule update, then return normally.
- //
- Status = PeiServicesGetBootMode (&BootMode);
- if (EFI_ERROR (Status) || (BootMode != BOOT_ON_FLASH_UPDATE)) {
- DEBUG ((EFI_D_ERROR, "Boot mode is not correct for capsule update path.\n"));
- Status = EFI_NOT_FOUND;
- goto Done;
- }
-
- //
- // User may set the same ScatterGatherList with several different variables,
- // so cache all ScatterGatherList for check later.
- //
- Status = PeiServicesLocatePpi (
- &gEfiPeiReadOnlyVariable2PpiGuid,
- 0,
- NULL,
- (VOID **) &PPIVariableServices
- );
- if (EFI_ERROR (Status)) {
- goto Done;
- }
- Size = sizeof (CapsuleDataPtr64);
- StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CHAR16), EFI_CAPSULE_VARIABLE_NAME);
- TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
- while (TRUE) {
- if (Index > 0) {
- UnicodeValueToString (TempVarName, 0, Index, 0);
- }
- Status = PPIVariableServices->GetVariable (
- PPIVariableServices,
- CapsuleVarName,
- &gEfiCapsuleVendorGuid,
- NULL,
- &Size,
- (VOID *) &CapsuleDataPtr64
- );
- if (EFI_ERROR (Status)) {
- //
- // There is no capsule variables, quit
- //
- DEBUG ((EFI_D_INFO,"Capsule variable Index = %d\n", Index));
- break;
- }
- VariableCount++;
- Index++;
- }
-
- DEBUG ((EFI_D_INFO,"Capsule variable count = %d\n", VariableCount));
-
- //
- // The last entry is the end flag.
- //
- Status = PeiServicesAllocatePool (
- (VariableCount + 1) * sizeof (EFI_PHYSICAL_ADDRESS),
- (VOID **)&VariableArrayAddress
- );
-
- if (Status != EFI_SUCCESS) {
- DEBUG ((EFI_D_ERROR, "AllocatePages Failed!, Status = %x\n", Status));
- goto Done;
- }
-
- ZeroMem (VariableArrayAddress, (VariableCount + 1) * sizeof (EFI_PHYSICAL_ADDRESS));
-
- //
- // Find out if we actually have a capsule.
- // GetCapsuleDescriptors depends on variable PPI, so it should run in 32-bit environment.
- //
- Status = GetCapsuleDescriptors (VariableArrayAddress);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Fail to find capsule variables.\n"));
- goto Done;
- }
-
-#ifdef MDE_CPU_IA32
- if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
- //
- // Switch to 64-bit mode to process capsule data when:
- // 1. When DXE phase is 64-bit
- // 2. When the buffer for 64-bit transition exists
- // 3. When Capsule X64 image is built in BIOS image
- // In 64-bit mode, we can process capsule data above 4GB.
- //
- CoalesceImageEntryPoint = 0;
- Status = GetLongModeContext (&LongModeBuffer);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Fail to find the variable for long mode context!\n"));
- Status = EFI_NOT_FOUND;
- goto Done;
- }
-
- Status = FindCapsuleCoalesceImage (&CoalesceImageEntryPoint, &CoalesceImageMachineType);
- if ((EFI_ERROR (Status)) || (CoalesceImageMachineType != EFI_IMAGE_MACHINE_X64)) {
- DEBUG ((EFI_D_ERROR, "Fail to find CapsuleX64 module in FV!\n"));
- Status = EFI_NOT_FOUND;
- goto Done;
- }
- ASSERT (CoalesceImageEntryPoint != 0);
- CoalesceEntry = (COALESCE_ENTRY) (UINTN) CoalesceImageEntryPoint;
- Status = ModeSwitch (&LongModeBuffer, CoalesceEntry, (EFI_PHYSICAL_ADDRESS)(UINTN)VariableArrayAddress, MemoryBase, MemorySize);
- } else {
- //
- // Capsule is processed in IA32 mode.
- //
- Status = CapsuleDataCoalesce (PeiServices, (EFI_PHYSICAL_ADDRESS *)(UINTN)VariableArrayAddress, MemoryBase, MemorySize);
- }
-#else
- //
- // Process capsule directly.
- //
- Status = CapsuleDataCoalesce (PeiServices, (EFI_PHYSICAL_ADDRESS *)(UINTN)VariableArrayAddress, MemoryBase, MemorySize);
-#endif
-
- DEBUG ((EFI_D_INFO, "Capsule Coalesce Status = %r!\n", Status));
-
- if (Status == EFI_BUFFER_TOO_SMALL) {
- DEBUG ((EFI_D_ERROR, "There is not enough memory to process capsule!\n"));
- }
-
- if (Status == EFI_NOT_FOUND) {
- DEBUG ((EFI_D_ERROR, "Fail to parse capsule descriptor in memory!\n"));
- REPORT_STATUS_CODE (
- EFI_ERROR_CODE | EFI_ERROR_MAJOR,
- (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_INVALID_CAPSULE_DESCRIPTOR)
- );
- }
-
-Done:
- return Status;
-}
-
-/**
- Determine if we're in capsule update boot mode.
-
- @param PeiServices PEI services table
-
- @retval EFI_SUCCESS if we have a capsule available
- @retval EFI_NOT_FOUND no capsule detected
-
-**/
-EFI_STATUS
-EFIAPI
-CheckCapsuleUpdate (
- IN EFI_PEI_SERVICES **PeiServices
- )
-{
- EFI_STATUS Status;
- Status = GetCapsuleDescriptors (NULL);
- return Status;
-}
-/**
- This function will look at a capsule and determine if it's a test pattern.
- If it is, then it will verify it and emit an error message if corruption is detected.
-
- @param PeiServices Standard pei services pointer
- @param CapsuleBase Base address of coalesced capsule, which is preceeded
- by private data. Very implementation specific.
-
- @retval TRUE Capsule image is the test image
- @retval FALSE Capsule image is not the test image.
-
-**/
-BOOLEAN
-CapsuleTestPattern (
- IN EFI_PEI_SERVICES **PeiServices,
- IN VOID *CapsuleBase
- )
-{
- UINT32 *TestPtr;
- UINT32 TestCounter;
- UINT32 TestSize;
- BOOLEAN RetValue;
-
- RetValue = FALSE;
-
- //
- // Look at the capsule data and determine if it's a test pattern. If it
- // is, then test it now.
- //
- TestPtr = (UINT32 *) CapsuleBase;
- //
- // 0x54534554 "TEST"
- //
- if (*TestPtr == 0x54534554) {
- RetValue = TRUE;
- DEBUG ((EFI_D_INFO, "Capsule test pattern mode activated...\n"));
- TestSize = TestPtr[1] / sizeof (UINT32);
- //
- // Skip over the signature and the size fields in the pattern data header
- //
- TestPtr += 2;
- TestCounter = 0;
- while (TestSize > 0) {
- if (*TestPtr != TestCounter) {
- DEBUG ((EFI_D_INFO, "Capsule test pattern mode FAILED: BaseAddr/FailAddr 0x%X 0x%X\n", (UINT32)(UINTN)(EFI_CAPSULE_PEIM_PRIVATE_DATA *)CapsuleBase, (UINT32)(UINTN)TestPtr));
- return TRUE;
- }
-
- TestPtr++;
- TestCounter++;
- TestSize--;
- }
-
- DEBUG ((EFI_D_INFO, "Capsule test pattern mode SUCCESS\n"));
- }
-
- return RetValue;
-}
-
-/**
- Capsule PPI service that gets called after memory is available. The
- capsule coalesce function, which must be called first, returns a base
- address and size, which can be anything actually. Once the memory init
- PEIM has discovered memory, then it should call this function and pass in
- the base address and size returned by the coalesce function. Then this
- function can create a capsule HOB and return.
-
- @param PeiServices standard pei services pointer
- @param CapsuleBase address returned by the capsule coalesce function. Most
- likely this will actually be a pointer to private data.
- @param CapsuleSize value returned by the capsule coalesce function.
-
- @retval EFI_VOLUME_CORRUPTED CapsuleBase does not appear to point to a
- coalesced capsule
- @retval EFI_SUCCESS if all goes well.
-**/
-EFI_STATUS
-EFIAPI
-CreateState (
- IN EFI_PEI_SERVICES **PeiServices,
- IN VOID *CapsuleBase,
- IN UINTN CapsuleSize
- )
-{
- EFI_STATUS Status;
- EFI_CAPSULE_PEIM_PRIVATE_DATA *PrivateData;
- UINTN Size;
- EFI_PHYSICAL_ADDRESS NewBuffer;
- UINTN CapsuleNumber;
- UINT32 Index;
- EFI_PHYSICAL_ADDRESS BaseAddress;
- UINT64 Length;
-
- PrivateData = (EFI_CAPSULE_PEIM_PRIVATE_DATA *) CapsuleBase;
- if (PrivateData->Signature != EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE) {
- return EFI_VOLUME_CORRUPTED;
- }
- if (PrivateData->CapsuleAllImageSize >= MAX_ADDRESS) {
- DEBUG ((EFI_D_ERROR, "CapsuleAllImageSize too big - 0x%lx\n", PrivateData->CapsuleAllImageSize));
- return EFI_OUT_OF_RESOURCES;
- }
- if (PrivateData->CapsuleNumber >= MAX_ADDRESS) {
- DEBUG ((EFI_D_ERROR, "CapsuleNumber too big - 0x%lx\n", PrivateData->CapsuleNumber));
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // Capsule Number and Capsule Offset is in the tail of Capsule data.
- //
- Size = (UINTN)PrivateData->CapsuleAllImageSize;
- CapsuleNumber = (UINTN)PrivateData->CapsuleNumber;
- //
- // Allocate the memory so that it gets preserved into DXE
- //
- Status = PeiServicesAllocatePages (
- EfiRuntimeServicesData,
- EFI_SIZE_TO_PAGES (Size),
- &NewBuffer
- );
-
- if (Status != EFI_SUCCESS) {
- DEBUG ((EFI_D_ERROR, "AllocatePages Failed!\n"));
- return Status;
- }
- //
- // Copy to our new buffer for DXE
- //
- DEBUG ((EFI_D_INFO, "Capsule copy from 0x%8X to 0x%8X with size 0x%8X\n", (UINTN)((UINT8 *)PrivateData + sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64)), (UINTN) NewBuffer, Size));
- CopyMem ((VOID *) (UINTN) NewBuffer, (VOID *) (UINTN) ((UINT8 *)PrivateData + sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64)), Size);
- //
- // Check for test data pattern. If it is the test pattern, then we'll
- // test it ans still create the HOB so that it can be used to verify
- // that capsules don't get corrupted all the way into BDS. BDS will
- // still try to turn it into a firmware volume, but will think it's
- // corrupted so nothing will happen.
- //
- DEBUG_CODE (
- CapsuleTestPattern (PeiServices, (VOID *) (UINTN) NewBuffer);
- );
-
- //
- // Build the UEFI Capsule Hob for each capsule image.
- //
- for (Index = 0; Index < CapsuleNumber; Index ++) {
- BaseAddress = NewBuffer + PrivateData->CapsuleOffset[Index];
- Length = ((EFI_CAPSULE_HEADER *)((UINTN) BaseAddress))->CapsuleImageSize;
-
- BuildCvHob (BaseAddress, Length);
- }
-
- return EFI_SUCCESS;
-}
-
-CONST EFI_PEI_CAPSULE_PPI mCapsulePpi = {
- CapsuleCoalesce,
- CheckCapsuleUpdate,
- CreateState
-};
-
-CONST EFI_PEI_PPI_DESCRIPTOR mUefiPpiListCapsule = {
- (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
- &gEfiPeiCapsulePpiGuid,
- (EFI_PEI_CAPSULE_PPI *) &mCapsulePpi
-};
-
-/**
- Entry point function for the PEIM
-
- @param FileHandle Handle of the file being invoked.
- @param PeiServices Describes the list of possible PEI Services.
-
- @return EFI_SUCCESS If we installed our PPI
-
-**/
-EFI_STATUS
-EFIAPI
-CapsuleMain (
- IN EFI_PEI_FILE_HANDLE FileHandle,
- IN CONST EFI_PEI_SERVICES **PeiServices
- )
-{
- //
- // Just produce our PPI
- //
- return PeiServicesInstallPpi (&mUefiPpiListCapsule);
-}
diff --git a/MdeModulePkg/Universal/CapsulePei/X64/PageFaultHandler.S b/MdeModulePkg/Universal/CapsulePei/X64/PageFaultHandler.S
deleted file mode 100644
index 9e17cc39ee..0000000000
--- a/MdeModulePkg/Universal/CapsulePei/X64/PageFaultHandler.S
+++ /dev/null
@@ -1,81 +0,0 @@
-## @file
-# This is the assembly code for page fault handler hook.
-#
-# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
-#
-# 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.
-#
-##
-
-ASM_GLOBAL ASM_PFX(PageFaultHandlerHook)
-ASM_PFX(PageFaultHandlerHook):
- addq $-0x10, %rsp
- # save rax
- movq %rax, 0x08(%rsp)
-
- # pushq %rax # save all volatile registers
- pushq %rcx
- pushq %rdx
- pushq %r8
- pushq %r9
- pushq %r10
- pushq %r11
- # save volatile fp registers
- # 68h + 08h(for alignment)
- addq $-0x70, %rsp
- stmxcsr 0x60(%rsp)
- movdqa %xmm0, 0x0(%rsp)
- movdqa %xmm1, 0x10(%rsp)
- movdqa %xmm2, 0x20(%rsp)
- movdqa %xmm3, 0x30(%rsp)
- movdqa %xmm4, 0x40(%rsp)
- movdqa %xmm5, 0x50(%rsp)
-
- addq $-0x20, %rsp
- call ASM_PFX(PageFaultHandler)
- addq $0x20, %rsp
-
- # load volatile fp registers
- ldmxcsr 0x60(%rsp)
- movdqa 0x0(%rsp), %xmm0
- movdqa 0x10(%rsp), %xmm1
- movdqa 0x20(%rsp), %xmm2
- movdqa 0x30(%rsp), %xmm3
- movdqa 0x40(%rsp), %xmm4
- movdqa 0x50(%rsp), %xmm5
- addq $0x70, %rsp
-
- popq %r11
- popq %r10
- popq %r9
- popq %r8
- popq %rdx
- popq %rcx
- # popq %rax # restore all volatile registers
-
- addq $0x10, %rsp
-
- # rax returned from PageFaultHandler is NULL or OriginalHandler address
- # NULL if the page fault is handled by PageFaultHandler
- # OriginalHandler address if the page fault is not handled by PageFaultHandler
- testq %rax, %rax
-
- # save OriginalHandler address
- movq %rax, -0x10(%rsp)
- # restore rax
- movq -0x08(%rsp), %rax
-
- jz L1
-
- # jump to OriginalHandler
- jmpq *-0x10(%rsp)
-
-L1:
- addq $0x08, %rsp # skip error code for PF
- iretq
diff --git a/MdeModulePkg/Universal/CapsulePei/X64/PageFaultHandler.asm b/MdeModulePkg/Universal/CapsulePei/X64/PageFaultHandler.asm
deleted file mode 100644
index 2f1eab72ef..0000000000
--- a/MdeModulePkg/Universal/CapsulePei/X64/PageFaultHandler.asm
+++ /dev/null
@@ -1,87 +0,0 @@
-;; @file
-; This is the assembly code for page fault handler hook.
-;
-; Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
-;
-; 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.
-;
-;;
-
-EXTERN PageFaultHandler:PROC
-
- .code
-
-PageFaultHandlerHook PROC
- add rsp, -10h
- ; save rax
- mov [rsp + 08h], rax
-
- ;push rax ; save all volatile registers
- push rcx
- push rdx
- push r8
- push r9
- push r10
- push r11
- ; save volatile fp registers
- ; 68h + 08h(for alignment)
- add rsp, -70h
- stmxcsr [rsp + 60h]
- movdqa [rsp + 0h], xmm0
- movdqa [rsp + 10h], xmm1
- movdqa [rsp + 20h], xmm2
- movdqa [rsp + 30h], xmm3
- movdqa [rsp + 40h], xmm4
- movdqa [rsp + 50h], xmm5
-
- add rsp, -20h
- call PageFaultHandler
- add rsp, 20h
-
- ; load volatile fp registers
- ldmxcsr [rsp + 60h]
- movdqa xmm0, [rsp + 0h]
- movdqa xmm1, [rsp + 10h]
- movdqa xmm2, [rsp + 20h]
- movdqa xmm3, [rsp + 30h]
- movdqa xmm4, [rsp + 40h]
- movdqa xmm5, [rsp + 50h]
- add rsp, 70h
-
- pop r11
- pop r10
- pop r9
- pop r8
- pop rdx
- pop rcx
- ;pop rax ; restore all volatile registers
-
- add rsp, 10h
-
- ; rax returned from PageFaultHandler is NULL or OriginalHandler address
- ; NULL if the page fault is handled by PageFaultHandler
- ; OriginalHandler address if the page fault is not handled by PageFaultHandler
- test rax, rax
-
- ; save OriginalHandler address
- mov [rsp - 10h], rax
- ; restore rax
- mov rax, [rsp - 08h]
-
- jz @F
-
- ; jump to OriginalHandler
- jmp qword ptr [rsp - 10h]
-
-@@:
- add rsp, 08h ; skip error code for PF
- iretq
-PageFaultHandlerHook ENDP
-
- END
diff --git a/MdeModulePkg/Universal/CapsulePei/X64/X64Entry.c b/MdeModulePkg/Universal/CapsulePei/X64/X64Entry.c
deleted file mode 100644
index 670e2c7d5f..0000000000
--- a/MdeModulePkg/Universal/CapsulePei/X64/X64Entry.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/** @file
- The X64 entrypoint is used to process capsule in long mode.
-
-Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
-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.
-
-**/
-
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/CpuExceptionHandlerLib.h>
-#include <Library/DebugAgentLib.h>
-#include "CommonHeader.h"
-
-#define EXCEPTION_VECTOR_NUMBER 0x22
-
-#define IA32_PG_P BIT0
-#define IA32_PG_RW BIT1
-#define IA32_PG_PS BIT7
-
-typedef struct _PAGE_FAULT_CONTEXT {
- BOOLEAN Page1GSupport;
- UINT64 PhyMask;
- UINTN PageFaultBuffer;
- UINTN PageFaultIndex;
- //
- // Store the uplink information for each page being used.
- //
- UINT64 *PageFaultUplink[EXTRA_PAGE_TABLE_PAGES];
- VOID *OriginalHandler;
-} PAGE_FAULT_CONTEXT;
-
-typedef struct _PAGE_FAULT_IDT_TABLE {
- PAGE_FAULT_CONTEXT PageFaultContext;
- IA32_IDT_GATE_DESCRIPTOR IdtEntryTable[EXCEPTION_VECTOR_NUMBER];
-} PAGE_FAULT_IDT_TABLE;
-
-/**
- Page fault handler.
-
-**/
-VOID
-EFIAPI
-PageFaultHandlerHook (
- VOID
- );
-
-/**
- Hook IDT with our page fault handler so that the on-demand paging works on page fault.
-
- @param[in, out] IdtEntry Pointer to IDT entry.
- @param[in, out] PageFaultContext Pointer to page fault context.
-
-**/
-VOID
-HookPageFaultHandler (
- IN OUT IA32_IDT_GATE_DESCRIPTOR *IdtEntry,
- IN OUT PAGE_FAULT_CONTEXT *PageFaultContext
- )
-{
- UINT32 RegEax;
- UINT8 PhysicalAddressBits;
- UINTN PageFaultHandlerHookAddress;
-
- AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
- if (RegEax >= 0x80000008) {
- AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
- PhysicalAddressBits = (UINT8) RegEax;
- } else {
- PhysicalAddressBits = 36;
- }
- PageFaultContext->PhyMask = LShiftU64 (1, PhysicalAddressBits) - 1;
- PageFaultContext->PhyMask &= (1ull << 48) - SIZE_4KB;
-
- //
- // Set Page Fault entry to catch >4G access
- //
- PageFaultHandlerHookAddress = (UINTN)PageFaultHandlerHook;
- PageFaultContext->OriginalHandler = (VOID *)(UINTN)(LShiftU64 (IdtEntry->Bits.OffsetUpper, 32) + IdtEntry->Bits.OffsetLow + (IdtEntry->Bits.OffsetHigh << 16));
- IdtEntry->Bits.OffsetLow = (UINT16)PageFaultHandlerHookAddress;
- IdtEntry->Bits.Selector = (UINT16)AsmReadCs ();
- IdtEntry->Bits.Reserved_0 = 0;
- IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
- IdtEntry->Bits.OffsetHigh = (UINT16)(PageFaultHandlerHookAddress >> 16);
- IdtEntry->Bits.OffsetUpper = (UINT32)(PageFaultHandlerHookAddress >> 32);
- IdtEntry->Bits.Reserved_1 = 0;
-
- if (PageFaultContext->Page1GSupport) {
- PageFaultContext->PageFaultBuffer = (UINTN)(AsmReadCr3 () & PageFaultContext->PhyMask) + EFI_PAGES_TO_SIZE(2);
- }else {
- PageFaultContext->PageFaultBuffer = (UINTN)(AsmReadCr3 () & PageFaultContext->PhyMask) + EFI_PAGES_TO_SIZE(6);
- }
- PageFaultContext->PageFaultIndex = 0;
- ZeroMem (PageFaultContext->PageFaultUplink, sizeof (PageFaultContext->PageFaultUplink));
-}
-
-/**
- Acquire page for page fault.
-
- @param[in, out] PageFaultContext Pointer to page fault context.
- @param[in, out] Uplink Pointer to up page table entry.
-
-**/
-VOID
-AcquirePage (
- IN OUT PAGE_FAULT_CONTEXT *PageFaultContext,
- IN OUT UINT64 *Uplink
- )
-{
- UINTN Address;
-
- Address = PageFaultContext->PageFaultBuffer + EFI_PAGES_TO_SIZE (PageFaultContext->PageFaultIndex);
- ZeroMem ((VOID *) Address, EFI_PAGES_TO_SIZE (1));
-
- //
- // Cut the previous uplink if it exists and wasn't overwritten.
- //
- if ((PageFaultContext->PageFaultUplink[PageFaultContext->PageFaultIndex] != NULL) && ((*PageFaultContext->PageFaultUplink[PageFaultContext->PageFaultIndex] & PageFaultContext->PhyMask) == Address)) {
- *PageFaultContext->PageFaultUplink[PageFaultContext->PageFaultIndex] = 0;
- }
-
- //
- // Link & Record the current uplink.
- //
- *Uplink = Address | IA32_PG_P | IA32_PG_RW;
- PageFaultContext->PageFaultUplink[PageFaultContext->PageFaultIndex] = Uplink;
-
- PageFaultContext->PageFaultIndex = (PageFaultContext->PageFaultIndex + 1) % EXTRA_PAGE_TABLE_PAGES;
-}
-
-/**
- The page fault handler that on-demand read >4G memory/MMIO.
-
- @retval NULL The page fault is correctly handled.
- @retval OriginalHandler The page fault is not handled and is passed through to original handler.
-
-**/
-VOID *
-EFIAPI
-PageFaultHandler (
- VOID
- )
-{
- IA32_DESCRIPTOR Idtr;
- PAGE_FAULT_CONTEXT *PageFaultContext;
- UINT64 PhyMask;
- UINT64 *PageTable;
- UINT64 PFAddress;
- UINTN PTIndex;
-
- //
- // Get the IDT Descriptor.
- //
- AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr);
- //
- // Then get page fault context by IDT Descriptor.
- //
- PageFaultContext = (PAGE_FAULT_CONTEXT *) (UINTN) (Idtr.Base - sizeof (PAGE_FAULT_CONTEXT));
- PhyMask = PageFaultContext->PhyMask;
-
- PFAddress = AsmReadCr2 ();
- DEBUG ((EFI_D_ERROR, "CapsuleX64 - PageFaultHandler: Cr2 - %lx\n", PFAddress));
-
- if (PFAddress >= PhyMask + SIZE_4KB) {
- return PageFaultContext->OriginalHandler;
- }
- PFAddress &= PhyMask;
-
- PageTable = (UINT64*)(UINTN)(AsmReadCr3 () & PhyMask);
-
- PTIndex = BitFieldRead64 (PFAddress, 39, 47);
- // PML4E
- if ((PageTable[PTIndex] & IA32_PG_P) == 0) {
- AcquirePage (PageFaultContext, &PageTable[PTIndex]);
- }
- PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & PhyMask);
- PTIndex = BitFieldRead64 (PFAddress, 30, 38);
- // PDPTE
- if (PageFaultContext->Page1GSupport) {
- PageTable[PTIndex] = (PFAddress & ~((1ull << 30) - 1)) | IA32_PG_P | IA32_PG_RW | IA32_PG_PS;
- } else {
- if ((PageTable[PTIndex] & IA32_PG_P) == 0) {
- AcquirePage (PageFaultContext, &PageTable[PTIndex]);
- }
- PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & PhyMask);
- PTIndex = BitFieldRead64 (PFAddress, 21, 29);
- // PD
- PageTable[PTIndex] = (PFAddress & ~((1ull << 21) - 1)) | IA32_PG_P | IA32_PG_RW | IA32_PG_PS;
- }
-
- return NULL;
-}
-
-
-/**
- The X64 entrypoint is used to process capsule in long mode then
- return to 32-bit protected mode.
-
- @param EntrypointContext Pointer to the context of long mode.
- @param ReturnContext Pointer to the context of 32-bit protected mode.
-
- @retval This function should never return actually.
-
-**/
-EFI_STATUS
-EFIAPI
-_ModuleEntryPoint (
- SWITCH_32_TO_64_CONTEXT *EntrypointContext,
- SWITCH_64_TO_32_CONTEXT *ReturnContext
-)
-{
- EFI_STATUS Status;
- IA32_DESCRIPTOR Ia32Idtr;
- IA32_DESCRIPTOR X64Idtr;
- PAGE_FAULT_IDT_TABLE PageFaultIdtTable;
- IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
-
- //
- // Save the IA32 IDT Descriptor
- //
- AsmReadIdtr ((IA32_DESCRIPTOR *) &Ia32Idtr);
-
- //
- // Setup X64 IDT table
- //
- ZeroMem (PageFaultIdtTable.IdtEntryTable, sizeof (IA32_IDT_GATE_DESCRIPTOR) * EXCEPTION_VECTOR_NUMBER);
- X64Idtr.Base = (UINTN) PageFaultIdtTable.IdtEntryTable;
- X64Idtr.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * EXCEPTION_VECTOR_NUMBER - 1);
- AsmWriteIdtr ((IA32_DESCRIPTOR *) &X64Idtr);
-
- //
- // Setup the default CPU exception handlers
- //
- Status = InitializeCpuExceptionHandlers (NULL);
- ASSERT_EFI_ERROR (Status);
-
- //
- // Hook page fault handler to handle >4G request.
- //
- PageFaultIdtTable.PageFaultContext.Page1GSupport = EntrypointContext->Page1GSupport;
- IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) (X64Idtr.Base + (14 * sizeof (IA32_IDT_GATE_DESCRIPTOR)));
- HookPageFaultHandler (IdtEntry, &(PageFaultIdtTable.PageFaultContext));
-
- //
- // Initialize Debug Agent to support source level debug
- //
- InitializeDebugAgent (DEBUG_AGENT_INIT_THUNK_PEI_IA32TOX64, (VOID *) &Ia32Idtr, NULL);
-
- //
- // Call CapsuleDataCoalesce to process capsule.
- //
- Status = CapsuleDataCoalesce (
- NULL,
- (EFI_PHYSICAL_ADDRESS *) (UINTN) EntrypointContext->BlockListAddr,
- (VOID **) (UINTN) EntrypointContext->MemoryBase64Ptr,
- (UINTN *) (UINTN) EntrypointContext->MemorySize64Ptr
- );
-
- ReturnContext->ReturnStatus = Status;
-
- //
- // Disable interrupt of Debug timer, since the new IDT table cannot work in long mode
- //
- SaveAndSetDebugTimerInterrupt (FALSE);
- //
- // Restore IA32 IDT table
- //
- AsmWriteIdtr ((IA32_DESCRIPTOR *) &Ia32Idtr);
-
- //
- // Finish to coalesce capsule, and return to 32-bit mode.
- //
- AsmDisablePaging64 (
- ReturnContext->ReturnCs,
- (UINT32) ReturnContext->ReturnEntryPoint,
- (UINT32) (UINTN) EntrypointContext,
- (UINT32) (UINTN) ReturnContext,
- (UINT32) (EntrypointContext->StackBufferBase + EntrypointContext->StackBufferLength)
- );
-
- //
- // Should never be here.
- //
- ASSERT (FALSE);
- return EFI_SUCCESS;
-} \ No newline at end of file