Step to UEFI (249)继续在PeiMain 中(8)

第一次进入PeiCore() 的时候,因为环境尚未准备好,所以很快就能执行到下面的代码:

  //
  // Call PEIM dispatcher
  //
  PeiDispatcher (SecCoreData, &PrivateData);

在这里会执行 PEIM的执行:

MdeModulePkg\Core\Pei\Dispatcher\Dispatcher.c
/**
  Conduct PEIM dispatch.

  @param SecCoreData     Points to a data structure containing information about the PEI core's operating
                         environment, such as the size and location of temporary RAM, the stack location and
                         the BFV location.
  @param Private         Pointer to the private data passed in from caller

**/
VOID
PeiDispatcher (
  IN CONST EFI_SEC_PEI_HAND_OFF  *SecCoreData,
  IN PEI_CORE_INSTANCE           *Private
  )

进去这个函数之后,因为刚开始内存并没有准备好,所以 (Private->PeiMemoryInstalled) 这个条件不会满足,会进入下面的do … while 循环。

  //
  // This is the main dispatch loop.  It will search known FVs for PEIMs and
  // attempt to dispatch them.  If any PEIM gets dispatched through a single
  // pass of the dispatcher, it will start over from the BFV again to see
  // if any new PEIMs dependencies got satisfied.  With a well ordered
  // FV where PEIMs are found in the order their dependencies are also
  // satisfied, this dispatcher should run only once.
  //

跳转到DiscoverPeimsAndOrderWithApriori() 函数中

      if (Private->CurrentPeimCount == 0) {
        //
        // When going through each FV, at first, search Apriori file to
        // reorder all PEIMs to ensure the PEIMs in Apriori file to get
        // dispatch at first.
        //
        DiscoverPeimsAndOrderWithApriori (Private, CoreFvHandle);
      }

这个函数的作用是找到所有的 PEIM以及Apriori 文件。

/**

  Discover all PEIMs and optional Apriori file in one FV. There is at most one
  Apriori file in one FV.


  @param Private          Pointer to the private data passed in from caller
  @param CoreFileHandle   The instance of PEI_CORE_FV_HANDLE.

**/
VOID
DiscoverPeimsAndOrderWithApriori (
  IN  PEI_CORE_INSTANCE    *Private,
  IN  PEI_CORE_FV_HANDLE   *CoreFileHandle
  )

函数中有一个 DEBUG 输出如下:

  DEBUG ((
    DEBUG_INFO,
    "%a(): Found 0x%x PEI FFS files in the %dth FV\n",
    __FUNCTION__,
    PeimCount,
    Private->CurrentPeimFvCount
));

对应的串口 Log 中有如下字样,就是说在找到了7个 PEIM

DiscoverPeimsAndOrderWithApriori(): Found 0x7 PEI FFS files in the 0th FV

为了更好的观测,加入代码,输出它找到的 PEIM 的 GUID:

      for (Index = 0; Index < PeimCount; Index++) {
        //
        // Make an array of file name GUIDs that matches the FileHandle array so we can convert
        // quickly from file name to file handle
        //
        Status = FvPpi->GetFileInfo (FvPpi, TempFileHandles[Index], &FileInfo);
        ASSERT_EFI_ERROR (Status);
        CopyMem (&TempFileGuid[Index], &FileInfo.FileName, sizeof(EFI_GUID));
		DEBUG ((DEBUG_INFO , "%g\n", FileInfo.FileName));
      }

然后可以在串口输出中看到多了如下的输出:

9B3ADA4F-AE56-4C24-8DEA-F03B7558AE50
A3610442-E69F-4DF3-82CA-2360C4031A23
9D225237-FA01-464C-A949-BAABC02D31D0
222C386D-5ABC-4FB4-B124-FBB82488ACF4
86D70125-BAA3-4296-A62F-602BEBBB9081
89E549B0-7CFE-449D-9BA3-10D8B2312D71
EDADEB9D-DDBA-48BD-9D22-C1C169C8C5C6

使用工具继续查看,可以将上面的GUID 和文件名对应起来:

GUID文件名
9B3ADA4F-AE56-4C24-8DEA-F03B7558AE50PcdPeim.efi
A3610442-E69F-4DF3-82CA-2360C4031A23ReportStatusCodeRouterPei.efi
9D225237-FA01-464C-A949-BAABC02D31D0StatusCodeHandlePei.efi
222C386D-5ABC-4FB4-B124-FBB82488ACF4PlatformPei.efi
86D70125-BAA3-4296-A62F-602BEBBB9081DxeIpl.efi
89E549B0-7CFE-449D-9BA3-10D8B2312D71S3Resume2Pei.efi
EDADEB9D-DDBA-48BD-9D22-C1C169C8C5C6CpuMpPei.efi

特别注意,用工具我们能看到9个文件(模块),但是这里只提示找到7个。

接下来退出      DiscoverPeimsAndOrderWithApriori() 函数继续在PeiDispatcher 中执行

     //
      // Start to dispatch all modules within the current FV.
      //

对于每一个 FFS文件,需要用DepexSatisfied()检查是否满足条件,如果满足会使用PeiLoadImage()

              //
              // For PEIM driver, Load its entry point
              //
              Status = PeiLoadImage (
                         PeiServices,
                         PeimFileHandle,
                         PEIM_STATE_NOT_DISPATCHED,
                         &EntryPoint,
                         &AuthenticationState
                         );

可以通过加入 Log 的方法证明这里调用的是位于\MdeModulePkg\Core\Pei\Image\Image.c 中的函数

/**
  Routine to load image file for subsequent execution by LoadFile Ppi.
  If any LoadFile Ppi is not found, the build-in support function for the PE32+/TE
  XIP image format is used.

  @param PeiServices     - An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
  @param FileHandle      - Pointer to the FFS file header of the image.
  @param PeimState       - The dispatch state of the input PEIM handle.
  @param EntryPoint      - Pointer to entry point of specified image file for output.
  @param AuthenticationState - Pointer to attestation authentication state of image.

  @retval EFI_SUCCESS    - Image is successfully loaded.
  @retval EFI_NOT_FOUND  - Fail to locate necessary PPI
  @retval Others         - Fail to load file.

**/
EFI_STATUS
PeiLoadImage (
  IN     CONST EFI_PEI_SERVICES       **PeiServices,
  IN     EFI_PEI_FILE_HANDLE          FileHandle,
  IN     UINT8                        PeimState,
  OUT    EFI_PHYSICAL_ADDRESS         *EntryPoint,
  OUT    UINT32                       *AuthenticationState
  )

其中通过如下调用来实现真正的加载:

      Status = LoadFile->LoadFile (
                          LoadFile,
                          FileHandle,
                          &ImageAddress,
                          &ImageSize,
                          EntryPoint,
                          AuthenticationState
                          );

实际的 Load动作是通过处于同一个文件中的PeiLoadImageLoadImageWrapper() 来实现的,而这个函数中实际干活的是PeiLoadImageLoadImage() 函数:

/**
  Loads a PEIM into memory for subsequent execution. If there are compressed
  images or images that need to be relocated into memory for performance reasons,
  this service performs that transformation.

  @param PeiServices      An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
  @param FileHandle       Pointer to the FFS file header of the image.
  @param ImageAddressArg  Pointer to PE/TE image.
  @param ImageSizeArg     Size of PE/TE image.
  @param EntryPoint       Pointer to entry point of specified image file for output.
  @param AuthenticationState - Pointer to attestation authentication state of image.

  @retval EFI_SUCCESS      Image is successfully loaded.
  @retval EFI_NOT_FOUND    Fail to locate necessary PPI.
  @retval EFI_UNSUPPORTED  Image Machine Type is not supported.
  @retval EFI_WARN_BUFFER_TOO_SMALL 
                           There is not enough heap to allocate the requested size.
                           This will not prevent the XIP image from being invoked.

**/
EFI_STATUS
PeiLoadImageLoadImage (
  IN     CONST EFI_PEI_SERVICES       **PeiServices,
  IN     EFI_PEI_FILE_HANDLE          FileHandle,
  OUT    EFI_PHYSICAL_ADDRESS         *ImageAddressArg,  OPTIONAL
  OUT    UINT64                       *ImageSizeArg,     OPTIONAL
  OUT    EFI_PHYSICAL_ADDRESS         *EntryPoint,
  OUT    UINT32                       *AuthenticationState
  )

  其中有2处使用 DEBUG 宏进行串口输出的代码(这里研究对象是 EDK2 202108,不同版本之间可能有差别)

  DEBUG ((DEBUG_INFO, "Loading PEIM %g\n", FileHandle));
   DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)*EntryPoint));

因此串口 Log 中看到的如下字样:

Loading PEIM 9B3ADA4F-AE56-4C24-8DEA-F03B7558AE50
Loading PEIM at 0x0000083D120 EntryPoint=0x0000083D620 PcdPeim.efi

接下的部分串口 Log就是来自PcdPeim.efi。

发表评论

您的电子邮箱地址不会被公开。