Newer
Older
AMI-Aptio-BIOS-Reversed / CapsulePei / CapsulePei.c
@Ajax Dong Ajax Dong 2 days ago 29 KB Init
/**
 * CapsulePei - Capsule PEIM
 *
 * Source: MdeModulePkg/Universal/CapsulePei/
 * Modules:
 *   - Common/CapsuleCoalesce.c  (capsule coalescing logic)
 *   - UefiCapsule.c             (UEFI capsule entry / PEI phase coordination)
 *
 * Binary: CapsulePei.efi (32-bit PEI)
 * Image size: 0x44e0
 * Functions: 61 (all renamed)
 */

#include <PiPei.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/PeiServicesLib.h>
#include <Library/HobLib.h>
#include <Library/BaseLib.h>
#include <Library/PrintLib.h>
#include <Ppi/Capsule.h>
#include <Guid/CapsuleVendor.h>

//
// Forward declarations
//
EFI_STATUS
EFIAPI
_ModuleEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  );

/*----------------------------------------------------------------------
 * Base Memory Routines (from BaseMemoryLibRepStr)
 *----------------------------------------------------------------------*/

/**
 * Copy memory (handles overlapping src/dst by doing backward copy).
 */
VOID *
InternalCopyMem (
  VOID        *Destination,
  CONST VOID  *Source,
  UINTN       Length
  )
{
  // Copies Length bytes from Source to Destination.
  // If Source < Destination and ranges overlap, copies backward.
  // Otherwise uses dword-aligned copy then residual.
}

/**
 * Zero-fill memory.
 */
VOID *
InternalZeroMem (
  VOID   *Buffer,
  UINTN  Length
  )
{
  return memset(Buffer, 0, Length);
}

/**
 * Set memory to a byte value.
 */
VOID *
InternalSetMem (
  VOID   *Buffer,
  UINTN  Length,
  UINT8  Value
  )
{
  return memset(Buffer, Value, Length);
}

/**
 * Set memory 32-bit values (count of UINT32).
 */
VOID *
InternalSetMem32 (
  VOID    *Buffer,
  UINTN   Count,
  UINT32  Value
  )
{
  // memset32-style fill
}

/**
 * Wrapper for setting memory 32-bit values with 64-bit pair.
 */
INTN
SetMem32Wrapper (
  INTN   Base,
  INTN   Count,
  INTN   ValueLow,
  INTN   ValueHigh
  )
{
  // Uses InternalSetMem32-style write in a counted loop
}

/*----------------------------------------------------------------------
 * x86 Architecture Primitives (from BaseLib)
 *----------------------------------------------------------------------*/

/**
 * Read IDTR register.
 */
VOID
ReadIdtr (
  OUT IA32_DESCRIPTOR  *Idtr
  )
{
  __sidt(Idtr);
}

/**
 * Write GDTR register.
 */
VOID
WriteGdtr (
  IN IA32_DESCRIPTOR  *Gdtr
  )
{
  __lgdt(Gdtr);
}

/**
 * CPUID instruction wrapper.
 */
UINT32
Cpuid (
  IN  UINT32  EaxIn,
  OUT UINT32  *Eax    OPTIONAL,
  OUT UINT32  *Ebx    OPTIONAL,
  OUT UINT32  *Ecx    OPTIONAL,
  OUT UINT32  *Edx    OPTIONAL
  )
{
  UINT32 EaxOut;
  __asm { cpuid }
  if (Eax) *Eax = EaxOut;
  if (Edx) *Edx = <edx_value>;
  return EaxOut;
}

/**
 * 64-bit left shift (Count must be < 64).
 */
UINT64
LShiftU64 (
  IN UINT64  Value,
  IN UINTN   Count
  )
{
  ASSERT (Count < 64);
  if ((Count & 0x20) == 0)
    return Value << (Count & 0x1F);
  else
    return Value << (Count & 0x1F);
}

/**
 * Read unaligned 64-bit value.
 */
UINT64
ReadUnaligned64 (
  IN CONST VOID  *Buffer
  )
{
  return *(UINT64 *)Buffer;
}

/**
 * SetJump implementation.
 */
UINTN
SetJump (
  OUT BASE_LIBRARY_JUMP_BUFFER  *JumpBuffer,
  IN  VOID                      *Context
  )
{
  // Saves callee-saved registers, stack pointer, and return address
  JumpBuffer->Ebx = EaxIn;
  JumpBuffer->Esi = EsiIn;
  JumpBuffer->Edi = EdiIn;
  JumpBuffer->Ebp = EbpIn;
  JumpBuffer->Esp = &JumpBuffer;
  return ((UINTN (*)(VOID))JumpBuffer->ReturnAddr)();
}

/**
 * LongJump implementation (indirect jump via [edx+0x14]).
 */
VOID
LongJump (
  IN VOID    *Function,
  IN UINT32  Param
  )
{
  __asm { jmp dword ptr [edx+0x14] }
}

/**
 * Validate JumpBuffer pointer for SetJump.
 */
VOID
SetJumpValidateBuffer (
  IN VOID  *JumpBuffer
  )
{
  ASSERT (JumpBuffer != NULL);
  ASSERT (((UINTN)JumpBuffer & 3) == 0);
}

/**
 * Enable 64-bit paging with SSE/CR4/CR0/EFER MSR setup.
 */
UINTN
AsmEnablePaging64 (
  VOID
  )
{
  _disable();
  // Prepare return address
  __writecr4(__readcr4() | 0x20);         // CR4.PAE
  __writemsr(0xC0000080, __readmsr(0xC0000080) | 0x100);  // EFER.LME
  __writecr0(__readcr0() | 0x80000000);   // CR0.PG
  // Jump to continuation
}

/**
 * Wrapper: validate entry point/stack then call AsmEnablePaging64.
 */
UINTN
AsmEnablePaging64Wrapper (
  IN UINT64   EntryPoint,
  IN UINTN    StackSize,
  IN UINTN    StackBuffer,
  IN UINTN    Context,
  IN UINT64   NewStack
  )
{
  ASSERT (EntryPoint != 0);
  ASSERT (NewStack != 0);
  return AsmEnablePaging64();
}

/*----------------------------------------------------------------------
 * Page Table / Long Mode Transition
 *----------------------------------------------------------------------*/

/**
 * Initialize 4-level page tables at the provided buffer.
 * Sets up 512 PML4 entries, each pointing to a PDP with 512 entries
 * mapping 2MB pages (0x200000 per page).
 */
VOID
PageTableInitialization (
  IN VOID   *PageTableBuffer,
  IN UINTN  ModeFlags
  )
{
  // If ModeFlags != 0 (x64): creates PML4[0..511] each pointing to
  //   a PDP table with 512 PDEs mapping 0x200000 pages.
  // If ModeFlags == 0: creates 512 PML4 entries with 0x40000000 pages.
  // Unused entries zeroed.
}

/**
 * Switch to long mode using the provided 32→64 thunk context.
 * Saves GDTR, page tables, stack pointer.
 */
EFI_STATUS
CapsuleLongModeSwitch (
  IN     UINT32  *ThunkContext,
  IN     UINT32  Param
  )
{
  WriteGdtr(&ThunkContext->Gdtr);
  SetJumpValidateBuffer(ThunkContext);
  LongJump(ThunkContext, 1);
  return GetReportStatusCodeInterface();  // should not return
}

/**
 * Core 32→64 thunk call: allocate page tables, switch to long mode,
 * call the target function, then return.
 */
UINTN
Thunk32To64Call (
  IN     UINT32  *PageTables,
  IN     VOID    *ThunkData
  )
{
  INTN Result;

  Result = SetJump(ThunkData);
  if (Result == 0) {
    // First call: set up page tables and long mode
    PageTableInitialization(PageTables);
    WriteGdtr(&GdtDescriptor);
    __writecr3((UINT32)PageTables);
    DEBUG ((DEBUG_INFO, "Thunk32To64 Stack Base: 0x%lx, Stack Size: 0x%lx\n",
            ThunkData->StackBase, ThunkData->StackSize));
    AsmEnablePaging64Wrapper (
      *(UINT64 *)ThunkData,
      ThunkData,
      0,
      PageTables,
      0,
      *(UINT64 *)(ThunkData + 8) + *(UINT64 *)(ThunkData + 16)
      );
  }
  if (ThunkData->Result)
    return ThunkData->Result | 0x80000000;
  return EFI_SUCCESS;
}

/*----------------------------------------------------------------------
 * PEI Services Wrappers
 *----------------------------------------------------------------------*/

/**
 * Retrieve PEI Services pointer from the IDTR base.
 */
EFI_PEI_SERVICES **
GetPeiServices (
  VOID
  )
{
  IA32_DESCRIPTOR  Idtr;
  EFI_PEI_SERVICES **PeiServices;

  ReadIdtr(&Idtr);
  PeiServices = *(EFI_PEI_SERVICES ***)(Idtr.Base - 4);
  ASSERT (PeiServices != NULL);
  return PeiServices;
}

/**
 * Locate a PPI.
 */
EFI_STATUS
LocatePpi (
  IN  EFI_GUID              *Guid,
  OUT VOID                  **PpiInterface
  )
{
  return (*GetPeiServices())->LocatePpi (Guid, 0, NULL, PpiInterface);
}

/**
 * Allocate boot-services pages.
 */
EFI_STATUS
AllocatePages (
  IN EFI_MEMORY_TYPE   MemoryType,
  IN UINTN             Pages,
  OUT EFI_PHYSICAL_ADDRESS  *Address
  )
{
  return (*GetPeiServices())->AllocatePages (MemoryType, Pages, Address);
}

/**
 * Install a PPI.
 */
EFI_STATUS
InstallCapsulePpi (
  VOID
  )
{
  // Installs the Capsule PPI with gEfiPeiCapsulePpiGuid
  return (*GetPeiServices())->InstallPpi (gCapsulePpiGuid);
}

/**
 * Get HOB list.
 */
EFI_HOB_HANDOFF_INFO_TABLE *
GetHobList (
  VOID
  )
{
  EFI_HOB_HANDOFF_INFO_TABLE *HobList;
  EFI_STATUS                 Status;

  Status = (*GetPeiServices())->GetHobList (&HobList);
  ASSERT_EFI_ERROR (Status);
  ASSERT (HobList != NULL);
  return HobList;
}

/**
 * Get first HOB of specific type from list.
 */
VOID *
GetFirstHob (
  VOID
  )
{
  VOID *Hob;
  Hob = GetHobList();
  if ((*GetPeiServices())->GetBootMode() < 0)
    Hob = NULL;
  return Hob;
}

/**
 * Walk HOB list to find a HOB matching the requested type.
 */
VOID *
GetNextHob (
  IN UINT16  HobType,
  IN VOID    *HobStart
  )
{
  ASSERT (HobStart != NULL);
  while (((EFI_HOB_GENERIC_HEADER *)HobStart)->HobType != HobType) {
    if (((EFI_HOB_GENERIC_HEADER *)HobStart)->HobType == EFI_HOB_TYPE_END_OF_HOB_LIST)
      return NULL;
    HobStart = (VOID *)((UINT8 *)HobStart + ((EFI_HOB_GENERIC_HEADER *)HobStart)->HobLength);
  }
  return HobStart;
}

/**
 * Compare two GUIDs.
 */
BOOLEAN
CompareGuid (
  IN EFI_GUID  *Guid1,
  IN EFI_GUID  *Guid2
  )
{
  return (ReadUnaligned64(Guid1)      == ReadUnaligned64(Guid2)   &&
          ReadUnaligned64(&Guid1->Data2) == ReadUnaligned64(&Guid2->Data2));
}

/**
 * Get PCD database pointer.
 */
VOID *
GetPcdDb (
  VOID
  )
{
  EFI_GUID gPcdPpiGuid = ...;
  VOID *PcdDb = NULL;
  LocatePpi (&gPcdPpiGuid, &PcdDb);
  return PcdDb;
}

/**
 * Get ReportStatusCode interface (from PCD or PPI).
 */
EFI_REPORT_STATUS_CODE_INTERFACE *
GetReportStatusCodeInterface (
  VOID
  )
{
  EFI_GUID gStatusCodePpiGuid;
  VOID *Interface = NULL;

  if (LocatePpi (&gStatusCodePpiGuid, &Interface) >= 0)
    return Interface;
  return NULL;
}

/**
 * Debug print via report status code.
 */
VOID
DebugPrint (
  IN UINTN        ErrorLevel,
  IN CONST CHAR8  *Format,
  ...
  )
{
  EFI_REPORT_STATUS_CODE_INTERFACE *Rsc;

  Rsc = GetReportStatusCodeInterface();
  if (Rsc && (GetPlatformType() & ErrorLevel))
    Rsc->ReportStatusCode (ErrorLevel, Format, VA_ARG_LIST);
}

/**
 * ASSERT print helper.
 */
VOID
AssertPrint (
  IN CONST CHAR8  *FileName,
  IN UINTN        LineNumber,
  IN CONST CHAR8  *Expression
  )
{
  EFI_REPORT_STATUS_CODE_INTERFACE *Rsc;

  Rsc = GetReportStatusCodeInterface();
  if (Rsc)
    Rsc->ReportStatusCode (EFI_ERROR_CODE, FileName, LineNumber, Expression);
}

/**
 * CopyMem wrapper with boundary checking.
 */
VOID *
CopyMem (
  VOID        *Destination,
  CONST VOID  *Source,
  UINTN       Length
  )
{
  ASSERT (Length <= (UINTN)-1 - (UINTN)Destination);
  ASSERT (Length <= (UINTN)-1 - (UINTN)Source);
  if (Destination == Source)
    return Destination;
  return InternalCopyMem (Destination, Source, Length);
}

/**
 * ZeroMem wrapper with boundary checking.
 */
VOID
ZeroMem (
  VOID   *Buffer,
  UINTN  Length
  )
{
  ASSERT (Buffer != NULL);
  ASSERT (Length <= (UINTN)-1 - (UINTN)Buffer + 1);
  InternalZeroMem (Buffer, Length);
}

/*----------------------------------------------------------------------
 * Platform identification
 *----------------------------------------------------------------------*/

/**
 * Determine platform type via CMOS/RTC.
 * Returns:
 *   0             - Normal/Unknown
 *   -2147483644   - Server platform
 *   -2147483578   - Other known platform
 */
EFI_STATUS
GetPlatformType (
  VOID
  )
{
  UINT8 Register;

  // Read CMOS index 0x4A
  __outbyte (0x70, __inbyte(0x70) & 0x80 | 0x4A);
  Register = __inbyte (0x71);

  if (Register <= 3) {
    // Normal range - small value
  } else if (Register == 0) {
    Register = (*(UINT8 *)0xFDAF0490 & 2) | 1;
    if (Register == 0)
      return EFI_SUCCESS;
  }

  if (Register == (UINT8)-1)
    return EFI_SUCCESS;
  if (Register == 1)
    return EFI_INVALID_PARAMETER;  // Server
  return EFI_ACCESS_DENIED;        // Other known
}

/*----------------------------------------------------------------------
 * String handling (CapsuleUpdateData variable)
 *----------------------------------------------------------------------*/

/**
 * Check if address overlaps with the "CapsuleUpdateData" string.
 */
BOOLEAN
IsOverlap (
  IN UINTN  Address,
  IN UINTN  Size
  )
{
  // Overlap check against L"CapsuleUpdateData" storage
}

/**
 * Check if string fits within given size.
 */
BOOLEAN
StrSizeCheck (
  IN UINTN   Address,
  IN UINTN   SizeElements
  )
{
  return IsOverlap (Address, 2 * SizeElements) == 0;
}

/**
 * Calculate length of L"CapsuleUpdateData" wide string.
 */
UINTN
StrLenCapsuleUpdateData (
  VOID
  )
{
  // Returns length of L"CapsuleUpdateData" (15 characters)
  return 15;
}

/**
 * Copy "CapsuleUpdateData" wide string to destination.
 */
INTN
StrCpyCapsuleUpdateData (
  OUT CHAR16  *Destination
  )
{
  // Copies "CapsuleUpdateData\0" to destination
}

/**
 * Calculate length of a wide string.
 */
UINTN
StrLen (
  IN CONST CHAR16  *String
  )
{
  UINTN Length = 0;
  while (*String++) {
    if (Length >= PcdGet32 (PcdMaximumUnicodeStringLength))
      break;
    Length++;
  }
  return Length;
}

/**
 * Set a wide string filled with a single character.
 */
CHAR16 *
StrNSetChar (
  OUT CHAR16  *String,
  IN  UINTN    Size,
  IN  INTN     Count,
  IN  CHAR16   Char
  )
{
  for (INTN i = 0; i < Count; i++) {
    if ((UINTN)String >= Size)
      break;
    *String++ = Char;
  }
  return String;
}

/*----------------------------------------------------------------------
 * Print support (PrintLib)
 *----------------------------------------------------------------------*/

/**
 * Convert UINT64 to decimal ASCII string.
 */
CHAR8 *
ConvertUint64ToDecimalString (
  OUT CHAR8   *Buffer,
  IN  UINT64  Value
  )
{
  // Converts Value to decimal string, stores in Buffer
}

/**
 * Unicode SPrint with alignment check.
 */
UINTN
AsciiSPrintUnicodeCheck (
  OUT CHAR8         *Buffer,
  IN  UINTN         BufferSize,
  IN  CONST CHAR8   *Format,
  ...
  )
{
  ASSERT (((UINTN)Buffer & 1) == 0);
  return InternalPrintLibSPrint (Buffer, BufferSize, Format, ...);
}

/**
 * Internal PrintLib SPrint implementation.
 */
UINTN
InternalPrintLibSPrint (
  OUT CHAR8         *Buffer,
  IN  UINTN         BufferSize,
  IN  CONST CHAR8   *Format,
  IN  VA_LIST       VaListMarker
  )
{
  // Full format string parser with number conversion
}

/*----------------------------------------------------------------------
 * PEI Capsule Entry Points (UefiCapsule.c)
 *----------------------------------------------------------------------*/

/**
 * Find the CapsuleX64 PE32+ image in the firmware volume.
 * Walks FV to locate the x64 capsule coalesce entrypoint.
 */
EFI_STATUS
FindCapsuleX64PeImage (
  IN  UINTN    CapsuleType,
  OUT UINT16   *CapsuleImageType
  )
{
  EFI_STATUS          Status;
  EFI_PEI_SERVICES    **PeiServices;
  UINTN               Index = 0;
  EFI_FV_INFO         FvInfo;
  EFI_GUID            *CapsuleGuid = &gEfiCapsuleVendorGuid;

  PeiServices = GetPeiServices();
  Status = (*PeiServices)->FfsFindNextVolume (PeiServices, 0, &FvInfo);

  while (!EFI_ERROR (Status)) {
    Status = (*PeiServices)->FfsFindFile (CapsuleGuid, FvInfo, &FvInfo);
    if (!EFI_ERROR (Status)) {
      // Found the capsule PE image
      if (LocatePpi (&gPeiCapsuleThunkPpiGuid, ...) < 0) {
        ASSERT_EFI_ERROR (FALSE);
      }
      // Locate PE32 section, get entry point
      *CapsuleImageType = GetPeCoffEntryPoint (SectionData);
      return EFI_SUCCESS;
    }
    Status = (*PeiServices)->FfsFindNextVolume (PeiServices, ++Index, &FvInfo);
  }
  return Status;
}

/**
 * Get the "CapsuleLongModeBuffer" variable from variable services.
 */
EFI_STATUS
GetLongModeBufferVariable (
  OUT CAPSULE_LONG_MODE_BUFFER  *Buffer
  )
{
  EFI_GUID  gCapsuleVendorGuid;
  UINTN     BufferSize = sizeof (CAPSULE_LONG_MODE_BUFFER);

  if (LocatePpi (&gPeiVariablePpiGuid, &VariablePpi) < 0) {
    ASSERT_EFI_ERROR (FALSE);
  }

  return VariablePpi->GetVariable (
                        L"CapsuleLongModeBuffer",
                        &gCapsuleVendorGuid,
                        0,
                        &BufferSize,
                        Buffer
                        );
}

/**
 * Determine the physical address width (bits) from CPUID or HOB.
 */
UINT8
GetPhysicalAddressBits (
  VOID
  )
{
  UINT8   PhysicalAddressBits;
  UINTN   Hob;
  UINT32  Eax, Edx;
  UINT32  MaxCpuId;

  Hob = GetHobList();
  if (GetNextHob (EFI_HOB_TYPE_CPU, Hob)) {
    PhysicalAddressBits = *(UINT8 *)(Hob + 8);
  } else {
    Cpuid (0, &MaxCpuId, NULL, NULL, NULL);
    if (MaxCpuId >= 0x80000008) {
      Cpuid (0x80000008, &Eax, NULL, NULL, NULL);
      PhysicalAddressBits = (UINT8)Eax;
    } else if (MaxCpuId >= 0x80000000) {
      Cpuid (0x80000000, &Eax, NULL, NULL, NULL);
      PhysicalAddressBits = (UINT8)Eax;
    } else {
      PhysicalAddressBits = 36;
    }
  }

  ASSERT (PhysicalAddressBits <= 52);
  if (PhysicalAddressBits > 48)
    return 48;
  return PhysicalAddressBits;
}

/**
 * Collect system memory resources from HOBs.
 */
EFI_STATUS
GetSystemMemoryResources (
  OUT EFI_MEMORY_DESCRIPTOR  **MemoryResources,
  OUT UINTN                  *BestResourceIndex
  )
{
  // Walk the HOB list, collect EFI_RESOURCE_MEMORY resources.
  // Returns the resource with largest descriptor.
}

/**
 * Get capsule variable entries from "CapsuleUpdateData".
 * Each entry is an {Address, Size} pair tracking pending capsules.
 */
EFI_STATUS
GetCapsuleVariableList (
  OUT CAPSULE_VARIABLE_ENTRY  *VariableEntries
  )
{
  // Enumerate all "CapsuleUpdateData" variable instances
  // Variable is gEfiCapsuleVendorGuid + L"CapsuleUpdateData" Name
}

/**
 * Get number of pending capsule variables.
 */
UINTN
GetCapsuleVariableCount (
  VOID
  )
{
  return GetCapsuleVariableList (NULL);
}

/**
 * Main capsule data coalescing entry point.
 * Orchestrates the full coalescing flow:
 *   1. Get system memory resources
 *   2. Read long mode buffer
 *   3. Find CapsuleX64 PE image
 *   4. Enumerate capsule variables
 *   5. Allocate/relocate capsule data
 *   6. Coalesce through x64 thunk
 */
EFI_STATUS
CapsuleDataCoalesceEntry (
  IN  UINTN          CapsuleType,
  OUT VOID           **CapsuleData,
  OUT UINTN          *CapsuleDataSize
  )
{
  DEBUG ((DEBUG_INFO, "Capsule variable Index = %d\n"));
  DEBUG ((DEBUG_INFO, "Capsule variable count = %d\n"));

  // Allocate storage for capsule variable list
  CapsuleVariableCount = GetCapsuleVariableCount();
  BufferSize = 8 * CapsuleVariableCount + 8;
  Status = (*GetPeiServices())->AllocatePages (BufferSize, &VariableList);
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_ERROR, "AllocatePages Failed!, Status = %x\n", Status));
    return Status;
  }
  ZeroMem (VariableList, BufferSize);

  Status = GetCapsuleVariableList (VariableList);
  if (!EFI_ERROR (Status)) {
    MemoryResources = GetSystemMemoryResources();
    GetLongModeBufferVariable (&LongModeBuffer);

    if (FindCapsuleX64PeImage (&CoalesceImageEntryPoint, &ImageType) < 0 ||
        ImageType != 0x86A4) {
      DEBUG ((DEBUG_ERROR, "Fail to find CapsuleX64 module in FV!\n"));
      return EFI_NOT_FOUND;
    }

    ASSERT (CoalesceImageEntryPoint != 0);
    Status = CapsuleCoalesce (
               &LongModeBuffer,
               (VOID *)CoalesceImageEntryPoint,
               VariableList,
               0,
               MemoryResources,
               (UINTN *)CapsuleData,
               (UINTN *)CapsuleDataSize
               );
  }
  return Status;
}

/*----------------------------------------------------------------------
 * Capsule Caching & Coalescing (UefiCapsule.c)
 *----------------------------------------------------------------------*/

/**
 * Cache all capsule data into contiguous memory and coalesce.
 *
 * Walks the capsule descriptor block list, validates, allocates
 * scratch pages, copies all capsule segments, then coalesces
 * in place into the final capsule header format.
 */
EFI_STATUS
CapsuleCacheAndCoalesce (
  IN  VOID     *CapsuleHeader,
  IN  UINTN    CapsuleSize
  )
{
  // Validate signature = 0x50637343 ("Csc")
  // Read capsule sizes and counts
  // Allocate pages for coalesced data
  // Copy segment by segment
  // Call CapsuleDataCoalesce to build final capsule
}

/*----------------------------------------------------------------------
 * Capsule Validation & Coalescing Logic (CapsuleCoalesce.c)
 *----------------------------------------------------------------------*/

/**
 * Validate that a memory address range is valid in system memory.
 */
BOOLEAN
ValidateMemoryAddress (
  IN  UINT64   Address,
  IN  UINT64   Size,
  IN  VOID     *MemoryResourceList,
  IN  BOOLEAN  ValidateResource
  )
{
  // Check Address + Size does not overflow
  // Verify range falls within one of the memory resources
}

/**
 * Validate capsule descriptor block list integrity.
 *
 * Walks the EFI_CAPSULE_BLOCK_DESCRIPTOR linked list:
 * - Each data block points to valid memory
 * - Each capsule header has valid flags/sizes
 * - Capsule count and total image sizes are consistent
 */
BOOLEAN
ValidateCapsuleIntegrity (
  IN EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockList
  )
{
  UINT64                    CapsuleSizeTotal = 0;
  UINT32                    CapsuleCount = 0;
  EFI_CAPSULE_HEADER       *CapsuleHeader;
  EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr = BlockList;

  DEBUG ((DEBUG_INFO, "ValidateCapsuleIntegrity\n"));

  while (Ptr->Length != 0 || Ptr->Union.DataBlock != 0) {
    if (((UINTN)Ptr & 7) != 0) {
      DEBUG ((DEBUG_ERROR, "ERROR: BlockList address failed alignment check\n"));
      return FALSE;
    }

    if (Ptr->Length != 0) {
      // Validate data block
      if (!ValidateMemoryAddress (Ptr->Union.DataBlock, Ptr->Length, 0, FALSE))
        return FALSE;

      if (CapsuleSizeTotal == 0) {
        // First capsule header
        CapsuleHeader = (EFI_CAPSULE_HEADER *)(UINTN)Ptr->Union.DataBlock;
        if (Ptr->Length < sizeof (EFI_CAPSULE_HEADER)) {
          DEBUG ((DEBUG_ERROR, "ERROR: Ptr->Length < sizeof(EFI_CAPSULE_HEADER)\n"));
          return FALSE;
        }
        CapsuleSizeTotal = CapsuleHeader->CapsuleImageSize;
        if (CapsuleHeader->HeaderSize > CapsuleSizeTotal) {
          DEBUG ((DEBUG_ERROR, "ERROR: HeaderSize > CapsuleImageSize\n"));
          return FALSE;
        }
        // Check flags: must have CAPSULE_FLAGS_PERSIST_ACROSS_RESET
        // but not INITIATE_RESET or some other exclude bit
        CapsuleCount++;
      }

      if (CapsuleSizeTotal < Ptr->Length) {
        DEBUG ((DEBUG_ERROR, "ERROR: CapsuleSize(0x%lx) < Ptr->Length(0x%lx)\n"));
        return FALSE;
      }
      CapsuleSizeTotal -= Ptr->Length;
      Ptr++;
    } else {
      // Continuation pointer
      Ptr = (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)Ptr->Union.Continuation;
    }
  }

  if (CapsuleCount == 0) {
    DEBUG ((DEBUG_ERROR, "ERROR: CapsuleCount == 0\n"));
    return FALSE;
  }

  if (CapsuleSizeTotal != 0) {
    DEBUG ((DEBUG_ERROR, "ERROR: CapsuleSizeTotal != 0\n"));
    return FALSE;
  }

  return TRUE;
}

/**
 * Resolve overlapping memory regions during capsule relocate.
 * Adjusts destination to skip regions already occupied by source.
 */
UINT64
CapsuleRelocateOverlap (
  IN  UINT64   SourceEnd,
  IN  UINT64   Dest,
  IN  UINT32   DestEnd,
  IN  UINT32   RelocateOffset
  )
{
  // Given a capsule descriptor chain at SourceEnd, walks
  // continuation entries to compute a safe relocation
  // destination that doesn't overlap source data.
}

/**
 * Relocate capsule descriptors from the descriptor chain,
 * copying data blocks to non-overlapping destinations.
 */
UINT64
CapsuleRelocateDescriptors (
  IN  EFI_CAPSULE_BLOCK_DESCRIPTOR  *DescriptorChain,
  IN  UINT32                        DescriptorCount,
  IN  VOID                          *DestBuffer,
  IN  UINT32                        DestBufferSize
  )
{
  // Walks all descriptors, copies data blocks
  // Handles overlap via CapsuleRelocateOverlap
}

/**
 * Parse capsule descriptor chain and verify consistency.
 * Returns total size, capsule count, and capsule image size.
 */
EFI_STATUS
GetCapsuleInfo (
  IN  EFI_CAPSULE_BLOCK_DESCRIPTOR  *Desc,
  OUT UINTN                         *TotalSize,
  OUT UINTN                         *DescriptorCount,
  OUT UINT32                        *CapsuleFlags,
  OUT UINT32                        *CapsuleImageSize
  )
{
  DEBUG ((DEBUG_INFO, "GetCapsuleInfo enter\n"));

  if (Desc == NULL) {
    ASSERT (Desc != NULL);
    return EFI_INVALID_PARAMETER;
  }

  // Walk descriptors, sum lengths, find capsule header
}

/**
 * Check capsule data for test pattern before coalescing.
 */
BOOLEAN
CapsuleTestPatternPreCoalesce (
  IN EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockList
  )
{
  // If the first data block has signature 0x54534554 ("TEST")
  // followed by sequence 0,1,2,..., then it passes as test pattern.
  DEBUG ((DEBUG_INFO, "CapsuleTestPatternPreCoalesce\n"));
}

/**
 * Build a linked capsule descriptor list from a flat descriptor array.
 */
EFI_STATUS
BuildCapsuleDescriptors (
  OUT EFI_CAPSULE_BLOCK_DESCRIPTOR  **Descriptor
  )
{
  // Chains all valid capsule descriptors together
  DEBUG ((DEBUG_INFO, "BuildCapsuleDescriptors enter\n"));
}

/**
 * Main capsule data coalesce logic.
 * Orchestrates: build descriptors → test pattern check →
 * get capsule info → allocate → copy → coalesce.
 */
EFI_STATUS
CapsuleDataCoalesce (
  IN  VOID     *CapsuleData,
  OUT VOID     **CoalescedData,
  OUT UINTN    *CoalescedDataSize
  )
{
  DEBUG ((DEBUG_INFO, "CapsuleDataCoalesce enter\n"));

  // 1. Build capsule descriptors
  // 2. Test pattern pre-coalesce check
  // 3. Get capsule info (sizes, count, flags)
  // 4. Allocate coalesced data buffer
  // 5. Copy/cache capsule data
  // 6. Relocate overlapping descriptors
  // 7. Store final coalesced pointer
}

/**
 * High-level capsule coalesce entry from x64 thunk.
 *
 * Parameters:
 *   a1  - CapsuleLongModeBuffer [AddressLow, AddressHigh, ...]
 *   a2  - CapsuleX64 PE entry point (destination for thunk)
 *   a3  - Capsule variable list
 *   a4  - Reserved/Flags
 *   a5  - Memory resource descriptors
 *   a6  - [Out] Coalesced data pointer
 *   a7  - [In/Out] Coalesced data size
 */
EFI_STATUS
CapsuleCoalesce (
  IN     UINT64  *CapsuleBuffer,
  IN     VOID    *CoalesceEntry,
  IN     VOID    *VariableList,
  IN     UINT32  Reserved,
  IN     VOID    *MemoryResources,
  OUT    UINTN   *CoalescedData,
  IN OUT UINTN   *CoalescedDataSize
  )
{
  UINT64                    CapsuleEnd;
  UINT64                    CapsuleStart;
  BOOLEAN                   IsLongMode;
  EFI_STATUS                Status;
  UINTN                     TotalCapsuleSize;
  UINTN                     CapsuleImageSize;
  UINT32                    MemoryAttributes;
  UINT8                     PlatformType;
  UINT8                     PhysicalAddressBits;
  CAPSULE_VARIABLE_ENTRY    VariableEntries[16];

  ZeroMem (VariableEntries, sizeof (VariableEntries));

  CapsuleStart = CoalesceData;
  CapsuleEnd   = *CoalescedDataSize;

  // Check platform capabilities
  Status = GetPcdDb();
  PlatformStatus = CallPpi(4);
  if (PlatformStatus) {
    // Determine if long mode is available
    IsLongMode = TRUE;
  }

  // Parse capsule buffer layout
  // CapsuleBuffer[0] = low address, [1] = high address
  CapsuleImageSize = *CoalescedData;
  TotalCapsuleSize  = *CoalescedDataSize;

  // Validate capsule range against system memory
  // ... complex range/overlap checking ...

  // Populate descriptor context
  VariableEntries[0]  = VariableList;
  VariableEntries[2]  = CapsuleBuffer + 2; // StackBase
  VariableEntries[3]  = CapsuleBuffer + 3;
  VariableEntries[4]  = CapsuleBuffer + 4;
  VariableEntries[5]  = CapsuleBuffer + 5;
  VariableEntries[6]  = CoalesceEntry;
  VariableEntries[8]  = Reserved;          // Reserved param
  VariableEntries[9]  = CapsuleBuffer;     // CapsuleStart
  VariableEntries[10] = MemoryResources;   // Memory descriptors
  VariableEntries[12] = &CapsuleEnd;
  VariableEntries[14] = &CapsuleImageSize;
  VariableEntries[1]  = 0;
  VariableEntries[11] = 0;
  VariableEntries[13] = 0;
  VariableEntries[15] = 0;

  // SGDT for GDTR save
  VariableEntries[7]  = 0;

  Status = Thunk32To64Call (CapsuleStart, CapsuleEnd);
  if (!EFI_ERROR (Status)) {
    *CoalescedData     = (UINTN)VariableEntries[12];
    *CoalescedDataSize = VariableEntries[14];
  }
  return Status;
}

/*----------------------------------------------------------------------
 * PE/COFF Helpers
 *----------------------------------------------------------------------*/

/**
 * Get entry point from PE/COFF image.
 * Handles PE32+ as well as TE image formats.
 */
UINT16
GetPeCoffEntryPoint (
  IN VOID  *Pe32Data
  )
{
  ASSERT (Pe32Data != NULL);

  if (*(UINT16 *)Pe32Data == EFI_IMAGE_DOS_SIGNATURE) {
    Pe32Data = (VOID *)((UINT8 *)Pe32Data + *(UINT16 *)((UINT8 *)Pe32Data + 60));
  }

  if (*(UINT16 *)Pe32Data == EFI_IMAGE_NT_SIGNATURE) {
    // PE32+ (PE32+)
    return ((EFI_IMAGE_NT_HEADERS64 *)Pe32Data)->OptionalHeader.AddressOfEntryPoint;
  }

  if (*(UINT32 *)Pe32Data == EFI_TE_IMAGE_HEADER_SIGNATURE) {
    // TE image
    return ((EFI_TE_IMAGE_HEADER *)Pe32Data)->AddressOfEntryPoint;
  }
  return 0;
}

/*----------------------------------------------------------------------
 * Module Entry Point
 *----------------------------------------------------------------------*/

/**
 * Capsule PEIM entry point.
 *
 * Installs the Capsule PPI which UEFI capsule processing uses to
 * detect and coalesce capsule updates during the PEI phase.
 *
 * On success: Capsule PPI is installed for DXE to use.
 * On failure: ASSERT on EFI error with debug output.
 */
EFI_STATUS
EFIAPI
_ModuleEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_PEI_SERVICES **PeiServices;
  EFI_STATUS       Status;

  PeiServices = GetPeiServices();
  Status = (*PeiServices)->NotifyPpi (&gCapsuleNotifyDescriptor);
  if (Status == EFI_ALREADY_STARTED) {
    // Already notified - this is expected on repeat calls
  } else if (EFI_ERROR (Status)) {
    // Install the Capsule PPI
    Status = CapsuleDataCoalesceEntry (&CoalescedCapsule, &CapsuleSize);
    if (EFI_ERROR (Status)) {
      DEBUG ((DEBUG_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
      ASSERT_EFI_ERROR (FALSE);
    }

    Status = (*PeiServices)->InstallPpi (&gCapsulePpiDescriptor);
    if (EFI_ERROR (Status)) {
      DEBUG ((DEBUG_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
      ASSERT_EFI_ERROR (FALSE);
    }
  }

  return EFI_SUCCESS;
}