summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaszlo Ersek <lersek@redhat.com>2015-11-30 18:41:20 +0000
committerlersek <lersek@Edk2>2015-11-30 18:41:20 +0000
commit9beac0d847bf9c299fe6c05b0fe7041a75bffa67 (patch)
treea8853eb7d340a3bb30c61f398aafa6ab48da1cb9
parent320b4f084a256e16a7f0cbfa5f0b5c8e0bb1a0ac (diff)
downloadedk2-9beac0d847bf9c299fe6c05b0fe7041a75bffa67.zip
edk2-9beac0d847bf9c299fe6c05b0fe7041a75bffa67.tar.gz
edk2-9beac0d847bf9c299fe6c05b0fe7041a75bffa67.tar.bz2
OvmfPkg: Sec: assert the build-time calculated end of the scratch buffer
The DecompressMemFvs() function in "OvmfPkg/Sec/SecMain.c" uses more memory, temporarily, than what PEIFV and DXEFV will ultimately need. First, it uses an output buffer for decompression, second, the decompression itself needs a scratch buffer (and this scratch buffer is the highest area that SEC uses). DecompressMemFvs() used to be called on normal boots only (ie. not on S3 resume), which is why the decompression output buffer and the scratch buffer were allowed to scribble over RAM. However, we'll soon start to worry during S3 resume that the runtime OS might tamper with the pre-decompressed PEIFV, and we'll decompress the firmware volumes on S3 resume too, from pristine flash. For this we'll need to know the end of the scratch buffer in advance, so we can prepare a non-malicious OS for it. Calculate the end of the scratch buffer statically in the FDF files, and assert in DecompressMemFvs() that the runtime decompression will match it. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19036 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r--OvmfPkg/DecomprScratchEnd.fdf.inc72
-rw-r--r--OvmfPkg/OvmfPkg.dec1
-rw-r--r--OvmfPkg/OvmfPkg.fdf.inc2
-rw-r--r--OvmfPkg/OvmfPkgIa32.fdf4
-rw-r--r--OvmfPkg/OvmfPkgIa32X64.fdf4
-rw-r--r--OvmfPkg/OvmfPkgX64.fdf4
-rw-r--r--OvmfPkg/Sec/SecMain.c8
-rw-r--r--OvmfPkg/Sec/SecMain.inf1
8 files changed, 93 insertions, 3 deletions
diff --git a/OvmfPkg/DecomprScratchEnd.fdf.inc b/OvmfPkg/DecomprScratchEnd.fdf.inc
new file mode 100644
index 0000000..eb5cd49
--- /dev/null
+++ b/OvmfPkg/DecomprScratchEnd.fdf.inc
@@ -0,0 +1,72 @@
+## @file
+# This FDF include file computes the end of the scratch buffer used in
+# DecompressMemFvs() [OvmfPkg/Sec/SecMain.c]. It is based on the decompressed
+# (ie. original) size of the LZMA-compressed section of the one FFS file in
+# the FVMAIN_COMPACT firmware volume.
+#
+# Copyright (C) 2015, Red Hat, Inc.
+#
+# 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.
+##
+
+# The GUID EE4E5898-3914-4259-9D6E-DC7BD79403CF means "LzmaCustomDecompress".
+# The decompressed output will have the following structure (see the file
+# "9E21FD93-9C72-4c15-8C4B-E77F1DB2D792SEC1.guided.dummy" in the
+# Build/Ovmf*/*/FV/Ffs/9E21FD93-9C72-4c15-8C4B-E77F1DB2D792/ directory):
+#
+# Size Contents
+# ------------------- --------------------------------------------------------
+# 4 EFI_COMMON_SECTION_HEADER, stating size 124 (0x7C) and
+# type 0x19 (EFI_SECTION_RAW). The purpose of this section
+# is to pad the start of PEIFV to 128 bytes.
+# 120 Zero bytes (padding).
+#
+# 4 EFI_COMMON_SECTION_HEADER, stating size
+# (PcdOvmfPeiMemFvSize + 4), and type 0x17
+# (EFI_SECTION_FIRMWARE_VOLUME_IMAGE).
+# PcdOvmfPeiMemFvSize PEIFV. Note that the above sizes pad the offset of this
+# object to 128 bytes. See also the "guided.dummy.txt"
+# file in the same directory.
+#
+# 4 EFI_COMMON_SECTION_HEADER, stating size 12 (0xC) and
+# type 0x19 (EFI_SECTION_RAW). The purpose of this section
+# is to pad the start of DXEFV to 16 bytes.
+# 8 Zero bytes (padding).
+#
+# 4 EFI_COMMON_SECTION_HEADER, stating size
+# (PcdOvmfDxeMemFvSize + 4), and type 0x17
+# (EFI_SECTION_FIRMWARE_VOLUME_IMAGE).
+# PcdOvmfDxeMemFvSize DXEFV. Note that the above sizes pad the offset of this
+# object to 16 bytes. See also the "guided.dummy.txt" file
+# in the same directory.
+#
+# The total size after decompression is (128 + PcdOvmfPeiMemFvSize + 16 +
+# PcdOvmfDxeMemFvSize).
+
+DEFINE OUTPUT_SIZE = (128 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize + 16 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize)
+
+# LzmaCustomDecompressLib uses a constant scratch buffer size of 64KB; see
+# SCRATCH_BUFFER_REQUEST_SIZE in
+# "MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompress.c".
+
+DEFINE DECOMP_SCRATCH_SIZE = 0x00010000
+
+# Note: when we use PcdOvmfDxeMemFvBase in this context, BaseTools have not yet
+# offset it with MEMFD's base address. For that reason we have to do it manually.
+#
+# The calculation below mirrors DecompressMemFvs() [OvmfPkg/Sec/SecMain.c].
+
+DEFINE OUTPUT_BASE = ($(MEMFD_BASE_ADDRESS) + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase + 0x00100000)
+DEFINE DECOMP_SCRATCH_BASE_UNALIGNED = ($(OUTPUT_BASE) + $(OUTPUT_SIZE))
+DEFINE DECOMP_SCRATCH_BASE_ALIGNMENT = 0x000FFFFF
+DEFINE DECOMP_SCRATCH_BASE_MASK = 0xFFF00000
+DEFINE DECOMP_SCRATCH_BASE = (($(DECOMP_SCRATCH_BASE_UNALIGNED) + $(DECOMP_SCRATCH_BASE_ALIGNMENT)) & $(DECOMP_SCRATCH_BASE_MASK))
+
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDecompressionScratchEnd = $(DECOMP_SCRATCH_BASE) + $(DECOMP_SCRATCH_SIZE)
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 47b0e69..1c9f831 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -106,6 +106,7 @@
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageBase|0x0|UINT32|0x18
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageSize|0x0|UINT32|0x19
gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize|0x0|UINT32|0x1a
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDecompressionScratchEnd|0x0|UINT32|0x1f
[PcdsDynamic, PcdsDynamicEx]
gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2
diff --git a/OvmfPkg/OvmfPkg.fdf.inc b/OvmfPkg/OvmfPkg.fdf.inc
index 486bbc6..441c35a 100644
--- a/OvmfPkg/OvmfPkg.fdf.inc
+++ b/OvmfPkg/OvmfPkg.fdf.inc
@@ -60,3 +60,5 @@ SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize = $(BLOCK_SIZ
SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwSpareBase = gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwWorkingBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize = 0x10000
+
+DEFINE MEMFD_BASE_ADDRESS = 0x800000
diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
index d4ae2f9..30bd3bc 100644
--- a/OvmfPkg/OvmfPkgIa32.fdf
+++ b/OvmfPkg/OvmfPkgIa32.fdf
@@ -78,7 +78,7 @@ FV = SECFV
################################################################################
[FD.MEMFD]
-BaseAddress = 0x800000
+BaseAddress = $(MEMFD_BASE_ADDRESS)
Size = 0xA00000
ErasePolarity = 1
BlockSize = 0x10000
@@ -384,6 +384,8 @@ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
}
}
+!include DecomprScratchEnd.fdf.inc
+
################################################################################
[Rule.Common.SEC]
diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
index 5b4d9dc..59c3362 100644
--- a/OvmfPkg/OvmfPkgIa32X64.fdf
+++ b/OvmfPkg/OvmfPkgIa32X64.fdf
@@ -78,7 +78,7 @@ FV = SECFV
################################################################################
[FD.MEMFD]
-BaseAddress = 0x800000
+BaseAddress = $(MEMFD_BASE_ADDRESS)
Size = 0xA00000
ErasePolarity = 1
BlockSize = 0x10000
@@ -384,6 +384,8 @@ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
}
}
+!include DecomprScratchEnd.fdf.inc
+
################################################################################
[Rule.Common.SEC]
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index 8b4dd60..6ba1948 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -78,7 +78,7 @@ FV = SECFV
################################################################################
[FD.MEMFD]
-BaseAddress = 0x800000
+BaseAddress = $(MEMFD_BASE_ADDRESS)
Size = 0xA00000
ErasePolarity = 1
BlockSize = 0x10000
@@ -384,6 +384,8 @@ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
}
}
+!include DecomprScratchEnd.fdf.inc
+
################################################################################
[Rule.Common.SEC]
diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c
index 0cf127a..93e3594 100644
--- a/OvmfPkg/Sec/SecMain.c
+++ b/OvmfPkg/Sec/SecMain.c
@@ -362,6 +362,14 @@ DecompressMemFvs (
OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdOvmfDxeMemFvBase) + SIZE_1MB);
ScratchBuffer = ALIGN_POINTER ((UINT8*) OutputBuffer + OutputBufferSize, SIZE_1MB);
+
+ DEBUG ((EFI_D_VERBOSE, "%a: OutputBuffer@%p+0x%x ScratchBuffer@%p+0x%x "
+ "PcdOvmfDecompressionScratchEnd=0x%x\n", __FUNCTION__, OutputBuffer,
+ OutputBufferSize, ScratchBuffer, ScratchBufferSize,
+ PcdGet32 (PcdOvmfDecompressionScratchEnd)));
+ ASSERT ((UINTN)ScratchBuffer + ScratchBufferSize ==
+ PcdGet32 (PcdOvmfDecompressionScratchEnd));
+
Status = ExtractGuidedSectionDecode (
Section,
&OutputBuffer,
diff --git a/OvmfPkg/Sec/SecMain.inf b/OvmfPkg/Sec/SecMain.inf
index 415731c..9e8571d 100644
--- a/OvmfPkg/Sec/SecMain.inf
+++ b/OvmfPkg/Sec/SecMain.inf
@@ -70,3 +70,4 @@
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress
gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDecompressionScratchEnd