From 6c128c65b5ec0e5b8b5a0ccb165f3afd29e485f8 Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Wed, 2 Aug 2017 09:54:47 +0800 Subject: Remove core packages since we can get them from edk2 repository Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang --- MdeModulePkg/Universal/CapsulePei/Capsule.h | 130 -- MdeModulePkg/Universal/CapsulePei/CapsulePei.inf | 96 -- MdeModulePkg/Universal/CapsulePei/CapsulePei.uni | Bin 2114 -> 0 bytes .../Universal/CapsulePei/CapsulePeiExtra.uni | Bin 1364 -> 0 bytes MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf | 59 - MdeModulePkg/Universal/CapsulePei/CapsuleX64.uni | Bin 2838 -> 0 bytes .../Universal/CapsulePei/CapsuleX64Extra.uni | Bin 1382 -> 0 bytes .../Universal/CapsulePei/Common/CapsuleCoalesce.c | 1254 -------------------- .../Universal/CapsulePei/Common/CommonHeader.h | 102 -- MdeModulePkg/Universal/CapsulePei/UefiCapsule.c | 1063 ----------------- .../Universal/CapsulePei/X64/PageFaultHandler.S | 81 -- .../Universal/CapsulePei/X64/PageFaultHandler.asm | 87 -- MdeModulePkg/Universal/CapsulePei/X64/X64Entry.c | 292 ----- 13 files changed, 3164 deletions(-) delete mode 100644 MdeModulePkg/Universal/CapsulePei/Capsule.h delete mode 100644 MdeModulePkg/Universal/CapsulePei/CapsulePei.inf delete mode 100644 MdeModulePkg/Universal/CapsulePei/CapsulePei.uni delete mode 100644 MdeModulePkg/Universal/CapsulePei/CapsulePeiExtra.uni delete mode 100644 MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf delete mode 100644 MdeModulePkg/Universal/CapsulePei/CapsuleX64.uni delete mode 100644 MdeModulePkg/Universal/CapsulePei/CapsuleX64Extra.uni delete mode 100644 MdeModulePkg/Universal/CapsulePei/Common/CapsuleCoalesce.c delete mode 100644 MdeModulePkg/Universal/CapsulePei/Common/CommonHeader.h delete mode 100644 MdeModulePkg/Universal/CapsulePei/UefiCapsule.c delete mode 100644 MdeModulePkg/Universal/CapsulePei/X64/PageFaultHandler.S delete mode 100644 MdeModulePkg/Universal/CapsulePei/X64/PageFaultHandler.asm delete mode 100644 MdeModulePkg/Universal/CapsulePei/X64/X64Entry.c (limited to 'MdeModulePkg/Universal/CapsulePei') 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.
- -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 -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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.
-# -# 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 Binary files a/MdeModulePkg/Universal/CapsulePei/CapsulePei.uni and /dev/null differ diff --git a/MdeModulePkg/Universal/CapsulePei/CapsulePeiExtra.uni b/MdeModulePkg/Universal/CapsulePei/CapsulePeiExtra.uni deleted file mode 100644 index 871be9b513..0000000000 Binary files a/MdeModulePkg/Universal/CapsulePei/CapsulePeiExtra.uni and /dev/null 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.
-# -# 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 Binary files a/MdeModulePkg/Universal/CapsulePei/CapsuleX64.uni and /dev/null differ diff --git a/MdeModulePkg/Universal/CapsulePei/CapsuleX64Extra.uni b/MdeModulePkg/Universal/CapsulePei/CapsuleX64Extra.uni deleted file mode 100644 index 88d5e2057c..0000000000 Binary files a/MdeModulePkg/Universal/CapsulePei/CapsuleX64Extra.uni and /dev/null 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.
-Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.
-This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include -#include - -#include - -#include -#include -#include -#include - -#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.
-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.
- -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.
-# -# 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.
-; -; 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.
-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 -#include -#include -#include -#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 -- cgit v1.2.3