The PEI dispatcher handles PEIMs and embedded firmware volume images.
PEIMs are loaded and called (1), while embedded firmware volume images are
recursively scanned (2) for PEIMs and for further embedded firmware volume
images. FirmwareVolmeInfoPpiNotifyCallback() is the function directly
producing the newly detected entries for the dispatcher.

    PeiDispatcher() [MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c]
(3)   DepexSatisfied()
(4)     PeiServicesFfsFindSectionData(DEPEX) [MdePkg/.../PeiServicesLib.c]
          PeiFfsFindSectionData() [MdeModulePkg/Core/Pei/FwVol/FwVol.c]
            PeiFfsFvPpiFindSectionByType()
              PeiFfsFvPpiFindSectionByType2()
                ProcessSection()
(5)               Decompress() [MdeModulePkg/Core/DxeIplPeim/DxeLoad.c]
                    AllocatePages() [MdePkg/.../PeiMemoryAllocationLib]
      if satisfied:
        PeiFfsFvPpiGetFileInfo() [MdeModulePkg/Core/Pei/FwVol/FwVol.c]
        if EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE:
(2)       ProcessFvFile()
            PeiServicesInstallFvInfo2Ppi() [MdePkg/.../PeiServicesLib]
              InternalPeiServicesInstallFvInfoPpi()
                PeiServicesInstallPpi()
                  FirmwareVolmeInfoPpiNotifyCallback() [.../FwVol.c]
                    ProcessFvFile()
                      ...
        else:
(1)       PeiLoadImage()

PeiDispatcher checks for dependency expressions first (3),  and the
type-dependent processing in (1) and (2) happens only if such a Depex is
satisfied (or absent).

Files of type EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE can have no Depex
sections, they are pure containers. DepexSatisfied() at (3) always returns
TRUE for them, so functionality is not directly harmed.

However, an EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE can be compressed. In
order to look up the (nonexistent) Depex section (4), the Decompress
routine (5) is called.

Unfortunately, the Decompress() routine allocates EfiBootServicesData
memory. This is not permitted on the S3 Resume path, but PeiDispatcher()
is part of the S3 Resume path.

The problem is triggered by OVMF's firmware structure:

  FD.OVMF
    FV.FVMAIN_COMPACT             uncompressed
      FV.MAINFV                   compressed with LzmaCompress
        individual PEI modules    uncompressed
        FV.DXEFV                  compressed with PI_NONE
          individual DXE modules  uncompressed
    FV.SECFV                      uncompressed

FV.MAINFV is decompressed by OVMF's SEC and is only exposed to the PEI
dispatcher in decompressed form, so that's not the problem. However
FV.DXEFV, which is a direct sibling of the PEIMs, is compressed (with the
PI_NONE === EFI_NOT_COMPRESSED compression subtype). This causes an
invalid EfiBootServicesData allocation during S3 Resume, inside the
useless Depex check.

Avoiding the allocation by restricting the Depex check in PeiDispatcher()
to PEIMs doesn't help: ProcessFvFile() under (2) triggers the same
allocation by calling PeiFfsFvPpiFindSectionByType2() -- it must
decompress the file in order to scan it.

Changing FV.DXEFV's encapsulation from COMPRESS to GUIDED won't help
either, because in that case ProcessSection() would want to call
EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI.ExtractSection(), which again
allocates memory.

Solve this by flattening FV.MAINFV:

  FD.OVMF
    FV.FVMAIN_COMPACT             uncompressed
      FV.MAINFV                   compressed with LzmaCompress
        individual PEI modules    uncompressed
        individual DXE modules    uncompressed
    FV.SECFV                      uncompressed

This way we avoid recursive processing, without hurting the efficiency of
the outermost compression (in FV.MAINFV).

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <ler...@redhat.com>
---
 OvmfPkg/OvmfPkgX64.fdf | 39 ++++++---------------------------------
 1 file changed, 6 insertions(+), 33 deletions(-)

diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index e435486..2508c22 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -250,6 +250,12 @@ APRIORI PEI {
   INF  MdeModulePkg/Universal/PCD/Pei/Pcd.inf
 }
 
+APRIORI DXE {
+  INF  MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+  INF  MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+  INF  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+}
+
 #
 #  PEI Phase modules
 #
@@ -261,39 +267,6 @@ INF  MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
 INF  OvmfPkg/EmuSmmPei/EmuSmmPei.inf
 INF  UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
 
-FILE FV_IMAGE = A4EF5A93-3F1B-4232-A1C4-F0910E6D1D9C {
-  SECTION COMPRESS PI_NONE {
-    SECTION FV_IMAGE = DXEFV
-  }
-}
-
-################################################################################
-
-[FV.DXEFV]
-BlockSize          = 0x10000
-FvAlignment        = 16
-ERASE_POLARITY     = 1
-MEMORY_MAPPED      = TRUE
-STICKY_WRITE       = TRUE
-LOCK_CAP           = TRUE
-LOCK_STATUS        = TRUE
-WRITE_DISABLED_CAP = TRUE
-WRITE_ENABLED_CAP  = TRUE
-WRITE_STATUS       = TRUE
-WRITE_LOCK_CAP     = TRUE
-WRITE_LOCK_STATUS  = TRUE
-READ_DISABLED_CAP  = TRUE
-READ_ENABLED_CAP   = TRUE
-READ_STATUS        = TRUE
-READ_LOCK_CAP      = TRUE
-READ_LOCK_STATUS   = TRUE
-
-APRIORI DXE {
-  INF  MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
-  INF  MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
-  INF  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
-}
-
 #
 # DXE Phase modules
 #
-- 
1.8.3.1



------------------------------------------------------------------------------
Sponsored by Intel(R) XDK 
Develop, test and display web and hybrid apps with a single code base.
Download it for free now!
http://pubads.g.doubleclick.net/gampad/clk?id=111408631&iu=/4140/ostg.clktrk
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to