第二次进入PEICORE流程

第一次进入PEICORE流程

https://blog.csdn.net/degen_/article/details/152898020

检查 PEI Core 是否已迁移到内存中

与第一次进入不同,第二次进入PeiMain时OldCoreData != NULL,内存已可供 PEI Core 使用

C 复制代码
if (OldCoreData->ShadowedPeiCore == NULL)

如果==NULL,去修复PrivateData

修复PrivateData

C 复制代码
OldCoreData->Ps    = &OldCoreData->ServiceTableShadow;
      OldCoreData->CpuIo = &OldCoreData->ServiceTableShadow.CpuIo;
      if (OldCoreData->HeapOffsetPositive) {
        OldCoreData->HobList.Raw = (VOID *)(OldCoreData->HobList.Raw + OldCoreData->HeapOffset);
        if (OldCoreData->UnknownFvInfo != NULL) {
          OldCoreData->UnknownFvInfo = (PEI_CORE_UNKNOW_FORMAT_FV_INFO *)((UINT8 *)OldCoreData->UnknownFvInfo + OldCoreData->HeapOffset);
        }

        if (OldCoreData->CurrentFvFileHandles != NULL) {
          OldCoreData->CurrentFvFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->CurrentFvFileHandles + OldCoreData->HeapOffset);
        }

        if (OldCoreData->PpiData.PpiList.PpiPtrs != NULL) {
          OldCoreData->PpiData.PpiList.PpiPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.PpiList.PpiPtrs + OldCoreData->HeapOffset);
        }

        if (OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs != NULL) {
          OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs + OldCoreData->HeapOffset);
        }

        if (OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs != NULL) {
          OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs + OldCoreData->HeapOffset);
        }

        OldCoreData->Fv = (PEI_CORE_FV_HANDLE *)((UINT8 *)OldCoreData->Fv + OldCoreData->HeapOffset);
        for (Index = 0; Index < OldCoreData->FvCount; Index++) {
          if (OldCoreData->Fv[Index].PeimState != NULL) {
            OldCoreData->Fv[Index].PeimState = (UINT8 *)OldCoreData->Fv[Index].PeimState + OldCoreData->HeapOffset;
          }

          if (OldCoreData->Fv[Index].FvFileHandles != NULL) {
            OldCoreData->Fv[Index].FvFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->Fv[Index].FvFileHandles + OldCoreData->HeapOffset);
          }
        }

        OldCoreData->TempFileGuid    = (EFI_GUID *)((UINT8 *)OldCoreData->TempFileGuid + OldCoreData->HeapOffset);
        OldCoreData->TempFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->TempFileHandles + OldCoreData->HeapOffset);
      }

强制重新定位调度表

C 复制代码
      OldCoreData->DelayedDispatchTable = NULL;

修复 PEI Services 表指针

C 复制代码
      SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES **)&OldCoreData->Ps);

初始化PEI Core链接库

C 复制代码
      ProcessLibraryConstructorList (NULL, (CONST EFI_PEI_SERVICES **)&OldCoreData->Ps);

包含DEBUG串口和ACPI计时器

更新交接信息表

C 复制代码
      HandoffInformationTable = OldCoreData->HobList.HandoffInformationTable;
      if (OldCoreData->HeapOffsetPositive) {
        HandoffInformationTable->EfiEndOfHobList = HandoffInformationTable->EfiEndOfHobList + OldCoreData->HeapOffset;
      } else {
        HandoffInformationTable->EfiEndOfHobList = HandoffInformationTable->EfiEndOfHobList - OldCoreData->HeapOffset;
      }

      HandoffInformationTable->EfiMemoryTop        = OldCoreData->PhysicalMemoryBegin + OldCoreData->PhysicalMemoryLength;
      HandoffInformationTable->EfiMemoryBottom     = OldCoreData->PhysicalMemoryBegin;
      HandoffInformationTable->EfiFreeMemoryTop    = OldCoreData->FreePhysicalMemoryTop;
      HandoffInformationTable->EfiFreeMemoryBottom = HandoffInformationTable->EfiEndOfHobList + sizeof (EFI_HOB_GENERIC_HEADER);

包括HOB列表结束地址和内存映射信息

迁移内存分配 HOB 中的内存基地址

C 复制代码
      ConvertMemoryAllocationHobs (OldCoreData);
C 复制代码
VOID
ConvertMemoryAllocationHobs (
  IN PEI_CORE_INSTANCE  *PrivateData
  )
{
  EFI_PEI_HOB_POINTERS       Hob;
  EFI_HOB_MEMORY_ALLOCATION  *MemoryAllocationHob;
  EFI_PHYSICAL_ADDRESS       OldMemPagesBase;
  UINTN                      OldMemPagesSize;

  if (PrivateData->MemoryPages.Size == 0) {
    //
    // No any memory page allocated in pre-memory phase.
    //
    return;
  }

  OldMemPagesBase = PrivateData->MemoryPages.Base;
  OldMemPagesSize = PrivateData->MemoryPages.Size;

  MemoryAllocationHob = NULL;
  Hob.Raw             = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);
  while (Hob.Raw != NULL) {
    MemoryAllocationHob = (EFI_HOB_MEMORY_ALLOCATION *)Hob.Raw;
    if ((MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress >= OldMemPagesBase) &&
        (MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress < (OldMemPagesBase + OldMemPagesSize))
        )
    {
      if (PrivateData->MemoryPages.OffsetPositive) {
        MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress += PrivateData->MemoryPages.Offset;
      } else {
        MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress -= PrivateData->MemoryPages.Offset;
      }
    }

    Hob.Raw = GET_NEXT_HOB (Hob);
    Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);
  }
}

迁移 PPI 指针到内存中

C 复制代码
      ConvertPpiPointers (SecCoreData, OldCoreData);
C 复制代码
VOID
ConvertPpiPointers (
  IN CONST EFI_SEC_PEI_HAND_OFF  *SecCoreData,
  IN PEI_CORE_INSTANCE           *PrivateData
  )
{
  UINT8  Index;

  //
  // Convert normal PPIs.
  //
  for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {
    ConvertSinglePpiPointer (
      SecCoreData,
      PrivateData,
      &PrivateData->PpiData.PpiList.PpiPtrs[Index]
      );
  }

  //
  // Convert Callback Notification PPIs.
  //
  for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {
    ConvertSinglePpiPointer (
      SecCoreData,
      PrivateData,
      &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index]
      );
  }

  //
  // Convert Dispatch Notification PPIs.
  //
  for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {
    ConvertSinglePpiPointer (
      SecCoreData,
      PrivateData,
      &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index]
      );
  }
}

在内存里分配连续区域

C 复制代码
      OldCoreData->PeiMemoryInstalled = TRUE;

      if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {
        DEBUG ((DEBUG_VERBOSE, "Early Migration - PPI lists before temporary RAM evacuation:\n"));
        DumpPpiList (OldCoreData);

        //
        // Migrate installed content from Temporary RAM to Permanent RAM at this
        // stage when PEI core still runs from a cached location.
        // FVs that doesn't contain PEI_CORE should be migrated here.
        //
        EvacuateTempRam (OldCoreData, SecCoreData);

        DEBUG ((DEBUG_VERBOSE, "Early Migration - PPI lists after temporary RAM evacuation:\n"));
        DumpPpiList (OldCoreData);
      }

准备第三次进入PEICORE

C 复制代码
      OldCoreData->PeimDispatcherReenter = TRUE;

      if ((PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) && (OldCoreData->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
        //
        // if Loading Module at Fixed Address is enabled, allocate the PEI code memory range usage bit map array.
        // Every bit in the array indicate the status of the corresponding memory page available or not
        //
        OldCoreData->PeiCodeMemoryRangeUsageBitMap = AllocateZeroPool (((PcdGet32 (PcdLoadFixAddressPeiCodePageNumber)>>6) + 1)*sizeof (UINT64));
      }

      //
      // Shadow PEI Core. When permanent memory is available, shadow
      // PEI Core and PEIMs to get high performance.
      //
      OldCoreData->ShadowedPeiCore = (PEICORE_FUNCTION_POINTER)(UINTN)PeiCore;
      if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
          ((HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME) && PcdGetBool (PcdShadowPeimOnS3Boot)) ||
          ((HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && PcdGetBool (PcdShadowPeimOnBoot)))
      {
        OldCoreData->ShadowedPeiCore = ShadowPeiCore (OldCoreData);
      }

      //
      // PEI Core has now been shadowed to memory.  Restart PEI Core in memory.
      //
      OldCoreData->ShadowedPeiCore (SecCoreData, PpiList, OldCoreData);

至此PEI Core 已经被映射到内存

相关推荐
乄夜27 分钟前
嵌入式面试高频!!!C语言(十四) STL(嵌入式八股文)
c语言·c++·stm32·单片机·mcu·面试·51单片机
时光不去5 小时前
java接口自动化之allure本地生成报告
运维·笔记·自动化
杨浦老苏6 小时前
简单直观的笔记管理器Poznote
笔记·docker·群晖
椰壳也可8 小时前
06_作业基于CubeMx实现按键控制LED灯(裸机)(立芯嵌入式笔记)
笔记·stm32·学习
im_AMBER10 小时前
Leetcode 52
笔记·学习·算法·leetcode
dqsh0610 小时前
树莓派5+Ubuntu24.04 LTS CH348 / CH9344 驱动安装 保姆级教程
linux·c语言·单片机·嵌入式硬件·iot
奔跑吧邓邓子11 小时前
【C语言实战(80)】C语言实战:从复盘到进阶,解锁编程新高度
c语言·进阶·复盘·终篇
wdfk_prog11 小时前
[Linux]学习笔记系列 -- [kernel]kallsyms
linux·笔记·学习
@曾记否12 小时前
如何在Keil5中在没有硬件支持的情况下使用Keil的模拟器(Simulator) + 调试窗口输出进行调试
c语言·stm32
烛衔溟12 小时前
C语言多级指针与函数指针:指针的高级用法
c语言·算法