]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/Sec/SecMain.c
OvmfPkg/SecMain: Fix stack switching to permanent memory
[mirror_edk2.git] / OvmfPkg / Sec / SecMain.c
index 0edc4f9af3cfbfee0f73c4d78f105a5ed0e7d939..f7fec3d8c03b93d73042e480e4400be41f22ce32 100644 (file)
@@ -1,7 +1,8 @@
 /** @file\r
   Main SEC phase code.  Transitions to PEI.\r
 \r
-  Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -28,6 +29,7 @@
 #include <Library/PeCoffGetEntryPointLib.h>\r
 #include <Library/PeCoffExtraActionLib.h>\r
 #include <Library/ExtractGuidedSectionLib.h>\r
+#include <Library/LocalApicLib.h>\r
 \r
 #include <Ppi/TemporaryRamSupport.h>\r
 \r
@@ -331,11 +333,13 @@ DecompressMemFvs (
   UINT32                            AuthenticationStatus;\r
   VOID                              *OutputBuffer;\r
   VOID                              *ScratchBuffer;\r
-  EFI_FIRMWARE_VOLUME_IMAGE_SECTION *FvSection;\r
+  EFI_COMMON_SECTION_HEADER         *FvSection;\r
   EFI_FIRMWARE_VOLUME_HEADER        *PeiMemFv;\r
   EFI_FIRMWARE_VOLUME_HEADER        *DxeMemFv;\r
+  UINT32                            FvHeaderSize;\r
+  UINT32                            FvSectionSize;\r
 \r
-  FvSection = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*) NULL;\r
+  FvSection = (EFI_COMMON_SECTION_HEADER*) NULL;\r
 \r
   Status = FindFfsFileAndSection (\r
              *Fv,\r
@@ -361,6 +365,14 @@ DecompressMemFvs (
 \r
   OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdOvmfDxeMemFvBase) + SIZE_1MB);\r
   ScratchBuffer = ALIGN_POINTER ((UINT8*) OutputBuffer + OutputBufferSize, SIZE_1MB);\r
+\r
+  DEBUG ((EFI_D_VERBOSE, "%a: OutputBuffer@%p+0x%x ScratchBuffer@%p+0x%x "\r
+    "PcdOvmfDecompressionScratchEnd=0x%x\n", __FUNCTION__, OutputBuffer,\r
+    OutputBufferSize, ScratchBuffer, ScratchBufferSize,\r
+    PcdGet32 (PcdOvmfDecompressionScratchEnd)));\r
+  ASSERT ((UINTN)ScratchBuffer + ScratchBufferSize ==\r
+    PcdGet32 (PcdOvmfDecompressionScratchEnd));\r
+\r
   Status = ExtractGuidedSectionDecode (\r
              Section,\r
              &OutputBuffer,\r
@@ -377,7 +389,7 @@ DecompressMemFvs (
              OutputBufferSize,\r
              EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
              0,\r
-             (EFI_COMMON_SECTION_HEADER**) &FvSection\r
+             &FvSection\r
              );\r
   if (EFI_ERROR (Status)) {\r
     DEBUG ((EFI_D_ERROR, "Unable to find PEI FV section\n"));\r
@@ -402,7 +414,7 @@ DecompressMemFvs (
              OutputBufferSize,\r
              EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
              1,\r
-             (EFI_COMMON_SECTION_HEADER**) &FvSection\r
+             &FvSection\r
              );\r
   if (EFI_ERROR (Status)) {\r
     DEBUG ((EFI_D_ERROR, "Unable to find DXE FV section\n"));\r
@@ -410,11 +422,19 @@ DecompressMemFvs (
   }\r
 \r
   ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);\r
-  ASSERT (SECTION_SIZE (FvSection) ==\r
-          (PcdGet32 (PcdOvmfDxeMemFvSize) + sizeof (*FvSection)));\r
+\r
+  if (IS_SECTION2 (FvSection)) {\r
+    FvSectionSize = SECTION2_SIZE (FvSection);\r
+    FvHeaderSize = sizeof (EFI_COMMON_SECTION_HEADER2);\r
+  } else {\r
+    FvSectionSize = SECTION_SIZE (FvSection);\r
+    FvHeaderSize = sizeof (EFI_COMMON_SECTION_HEADER);\r
+  }\r
+\r
+  ASSERT (FvSectionSize == (PcdGet32 (PcdOvmfDxeMemFvSize) + FvHeaderSize));\r
 \r
   DxeMemFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfDxeMemFvBase);\r
-  CopyMem (DxeMemFv, (VOID*) (FvSection + 1), PcdGet32 (PcdOvmfDxeMemFvSize));\r
+  CopyMem (DxeMemFv, (VOID*) ((UINTN)FvSection + FvHeaderSize), PcdGet32 (PcdOvmfDxeMemFvSize));\r
 \r
   if (DxeMemFv->Signature != EFI_FVH_SIGNATURE) {\r
     DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", DxeMemFv));\r
@@ -469,6 +489,50 @@ FindPeiCoreImageBaseInFv (
   return EFI_SUCCESS;\r
 }\r
 \r
+\r
+/**\r
+  Reads 8-bits of CMOS data.\r
+\r
+  Reads the 8-bits of CMOS data at the location specified by Index.\r
+  The 8-bit read value is returned.\r
+\r
+  @param  Index  The CMOS location to read.\r
+\r
+  @return The value read.\r
+\r
+**/\r
+STATIC\r
+UINT8\r
+CmosRead8 (\r
+  IN      UINTN                     Index\r
+  )\r
+{\r
+  IoWrite8 (0x70, (UINT8) Index);\r
+  return IoRead8 (0x71);\r
+}\r
+\r
+\r
+STATIC\r
+BOOLEAN\r
+IsS3Resume (\r
+  VOID\r
+  )\r
+{\r
+  return (CmosRead8 (0xF) == 0xFE);\r
+}\r
+\r
+\r
+STATIC\r
+EFI_STATUS\r
+GetS3ResumePeiFv (\r
+  IN OUT EFI_FIRMWARE_VOLUME_HEADER       **PeiFv\r
+  )\r
+{\r
+  *PeiFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfPeiMemFvBase);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
 /**\r
   Locates the PEI Core entry point address\r
 \r
@@ -486,11 +550,29 @@ FindPeiCoreImageBase (
      OUT  EFI_PHYSICAL_ADDRESS             *PeiCoreImageBase\r
   )\r
 {\r
+  BOOLEAN S3Resume;\r
+\r
   *PeiCoreImageBase = 0;\r
 \r
-  FindMainFv (BootFv);\r
+  S3Resume = IsS3Resume ();\r
+  if (S3Resume && !FeaturePcdGet (PcdSmmSmramRequire)) {\r
+    //\r
+    // A malicious runtime OS may have injected something into our previously\r
+    // decoded PEI FV, but we don't care about that unless SMM/SMRAM is required.\r
+    //\r
+    DEBUG ((EFI_D_VERBOSE, "SEC: S3 resume\n"));\r
+    GetS3ResumePeiFv (BootFv);\r
+  } else {\r
+    //\r
+    // We're either not resuming, or resuming "securely" -- we'll decompress\r
+    // both PEI FV and DXE FV from pristine flash.\r
+    //\r
+    DEBUG ((EFI_D_VERBOSE, "SEC: %a\n",\r
+      S3Resume ? "S3 resume (with PEI decompression)" : "Normal boot"));\r
+    FindMainFv (BootFv);\r
 \r
-  DecompressMemFvs (BootFv);\r
+    DecompressMemFvs (BootFv);\r
+  }\r
 \r
   FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);\r
 }\r
@@ -587,7 +669,7 @@ FindImageBase (
 /*\r
   Find and return Pei Core entry point.\r
 \r
-  It also find SEC and PEI Core file debug inforamtion. It will report them if\r
+  It also find SEC and PEI Core file debug information. It will report them if\r
   remote debug is enabled.\r
 \r
 **/\r
@@ -647,6 +729,19 @@ SecCoreStartupWithStack (
   SEC_IDT_TABLE               IdtTableInStack;\r
   IA32_DESCRIPTOR             IdtDescriptor;\r
   UINT32                      Index;\r
+  volatile UINT8              *Table;\r
+\r
+  //\r
+  // To ensure SMM can't be compromised on S3 resume, we must force re-init of\r
+  // the BaseExtractGuidedSectionLib. Since this is before library contructors\r
+  // are called, we must use a loop rather than SetMem.\r
+  //\r
+  Table = (UINT8*)(UINTN)FixedPcdGet64 (PcdGuidedExtractHandlerTableAddress);\r
+  for (Index = 0;\r
+       Index < FixedPcdGet32 (PcdGuidedExtractHandlerTableSize);\r
+       ++Index) {\r
+    Table[Index] = 0;\r
+  }\r
 \r
   ProcessLibraryConstructorList (NULL, NULL);\r
 \r
@@ -717,6 +812,14 @@ SecCoreStartupWithStack (
   //\r
   IoWrite8 (0x21, 0xff);\r
   IoWrite8 (0xA1, 0xff);\r
+\r
+  //\r
+  // Initialize Local APIC Timer hardware and disable Local APIC Timer\r
+  // interrupts before initializing the Debug Agent and the debug timer is\r
+  // enabled.\r
+  //\r
+  InitializeApicTimer (0, MAX_UINT32, TRUE, 5);\r
+  DisableApicTimerInterrupt ();\r
   \r
   //\r
   // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.\r
@@ -786,10 +889,10 @@ TemporaryRamMigration (
   BASE_LIBRARY_JUMP_BUFFER         JumpBuffer;\r
   \r
   DEBUG ((EFI_D_INFO,\r
-    "TemporaryRamMigration(0x%x, 0x%x, 0x%x)\n",\r
-    (UINTN) TemporaryMemoryBase,\r
-    (UINTN) PermanentMemoryBase,\r
-    CopySize\r
+    "TemporaryRamMigration(0x%Lx, 0x%Lx, 0x%Lx)\n",\r
+    TemporaryMemoryBase,\r
+    PermanentMemoryBase,\r
+    (UINT64)CopySize\r
     ));\r
   \r
   OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;\r
@@ -828,9 +931,11 @@ TemporaryRamMigration (
   if (SetJump (&JumpBuffer) == 0) {\r
 #if defined (MDE_CPU_IA32)\r
     JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset;\r
+    JumpBuffer.Ebp = JumpBuffer.Ebp + DebugAgentContext.StackMigrateOffset;\r
 #endif    \r
 #if defined (MDE_CPU_X64)\r
     JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset;\r
+    JumpBuffer.Rbp = JumpBuffer.Rbp + DebugAgentContext.StackMigrateOffset;\r
 #endif    \r
     LongJump (&JumpBuffer, (UINTN)-1);\r
   }\r