]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/Sec/SecMain.c
OvmfPkg/Sec: Don't decompress the FV on S3 resume
[mirror_edk2.git] / OvmfPkg / Sec / SecMain.c
index e235b964a8009b40e827d197da489ea11145ad64..670ad8d763aab0dc3a5f8215ee57c96a3cf7c6dd 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Main SEC phase code.  Transitions to PEI.\r
 \r
-  Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<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
@@ -128,9 +128,13 @@ FindMainFv (
   Locates a section within a series of sections\r
   with the specified section type.\r
 \r
+  The Instance parameter indicates which instance of the section\r
+  type to return. (0 is first instance, 1 is second...)\r
+\r
   @param[in]   Sections        The sections to search\r
   @param[in]   SizeOfSections  Total size of all sections\r
   @param[in]   SectionType     The section type to locate\r
+  @param[in]   Instance        The section instance number\r
   @param[out]  FoundSection    The FFS section if found\r
 \r
   @retval EFI_SUCCESS           The file and section was found\r
@@ -139,10 +143,11 @@ FindMainFv (
 \r
 **/\r
 EFI_STATUS\r
-FindFfsSectionInSections (\r
+FindFfsSectionInstance (\r
   IN  VOID                             *Sections,\r
   IN  UINTN                            SizeOfSections,\r
   IN  EFI_SECTION_TYPE                 SectionType,\r
+  IN  UINTN                            Instance,\r
   OUT EFI_COMMON_SECTION_HEADER        **FoundSection\r
   )\r
 {\r
@@ -167,7 +172,6 @@ FindFfsSectionInSections (
     }\r
 \r
     Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;\r
-    DEBUG ((EFI_D_INFO, "Section->Type: 0x%x\n", Section->Type));\r
 \r
     Size = SECTION_SIZE (Section);\r
     if (Size < sizeof (*Section)) {\r
@@ -183,15 +187,49 @@ FindFfsSectionInSections (
     // Look for the requested section type\r
     //\r
     if (Section->Type == SectionType) {\r
-      *FoundSection = Section;\r
-      return EFI_SUCCESS;\r
+      if (Instance == 0) {\r
+        *FoundSection = Section;\r
+        return EFI_SUCCESS;\r
+      } else {\r
+        Instance--;\r
+      }\r
     }\r
-    DEBUG ((EFI_D_INFO, "Section->Type (0x%x) != SectionType (0x%x)\n", Section->Type, SectionType));\r
   }\r
 \r
   return EFI_NOT_FOUND;\r
 }\r
 \r
+/**\r
+  Locates a section within a series of sections\r
+  with the specified section type.\r
+\r
+  @param[in]   Sections        The sections to search\r
+  @param[in]   SizeOfSections  Total size of all sections\r
+  @param[in]   SectionType     The section type to locate\r
+  @param[out]  FoundSection    The FFS section if found\r
+\r
+  @retval EFI_SUCCESS           The file and section was found\r
+  @retval EFI_NOT_FOUND         The file and section was not found\r
+  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted\r
+\r
+**/\r
+EFI_STATUS\r
+FindFfsSectionInSections (\r
+  IN  VOID                             *Sections,\r
+  IN  UINTN                            SizeOfSections,\r
+  IN  EFI_SECTION_TYPE                 SectionType,\r
+  OUT EFI_COMMON_SECTION_HEADER        **FoundSection\r
+  )\r
+{\r
+  return FindFfsSectionInstance (\r
+           Sections,\r
+           SizeOfSections,\r
+           SectionType,\r
+           0,\r
+           FoundSection\r
+           );\r
+}\r
+\r
 /**\r
   Locates a FFS file with the specified file type and a section\r
   within that file with the specified section type.\r
@@ -207,7 +245,6 @@ FindFfsSectionInSections (
 \r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 FindFfsFileAndSection (\r
   IN  EFI_FIRMWARE_VOLUME_HEADER       *Fv,\r
   IN  EFI_FV_FILETYPE                  FileType,\r
@@ -223,7 +260,7 @@ FindFfsFileAndSection (
   EFI_PHYSICAL_ADDRESS        EndOfFile;\r
 \r
   if (Fv->Signature != EFI_FVH_SIGNATURE) {\r
-    DEBUG ((EFI_D_INFO, "FV at %p does not have FV header signature\n", Fv));\r
+    DEBUG ((EFI_D_ERROR, "FV at %p does not have FV header signature\n", Fv));\r
     return EFI_VOLUME_CORRUPTED;\r
   }\r
 \r
@@ -245,7 +282,6 @@ FindFfsFileAndSection (
     if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) {\r
       return EFI_VOLUME_CORRUPTED;\r
     }\r
-    DEBUG ((EFI_D_INFO, "File->Type: 0x%x\n", File->Type));\r
 \r
     EndOfFile = CurrentAddress + Size;\r
     if (EndOfFile > EndOfFirmwareVolume) {\r
@@ -256,7 +292,6 @@ FindFfsFileAndSection (
     // Look for the request file type\r
     //\r
     if (File->Type != FileType) {\r
-      DEBUG ((EFI_D_INFO, "File->Type (0x%x) != FileType (0x%x)\n", File->Type, FileType));\r
       continue;\r
     }\r
 \r
@@ -276,7 +311,7 @@ FindFfsFileAndSection (
   Locates the compressed main firmware volume and decompresses it.\r
 \r
   @param[in,out]  Fv            On input, the firmware volume to search\r
-                                On output, the decompressed main FV\r
+                                On output, the decompressed BOOT/PEI FV\r
 \r
   @retval EFI_SUCCESS           The file and section was found\r
   @retval EFI_NOT_FOUND         The file and section was not found\r
@@ -284,8 +319,7 @@ FindFfsFileAndSection (
 \r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
-DecompressGuidedFv (\r
+DecompressMemFvs (\r
   IN OUT EFI_FIRMWARE_VOLUME_HEADER       **Fv\r
   )\r
 {\r
@@ -297,10 +331,11 @@ DecompressGuidedFv (
   UINT32                            AuthenticationStatus;\r
   VOID                              *OutputBuffer;\r
   VOID                              *ScratchBuffer;\r
-  EFI_FIRMWARE_VOLUME_IMAGE_SECTION *NewFvSection;\r
-  EFI_FIRMWARE_VOLUME_HEADER        *NewFv;\r
+  EFI_FIRMWARE_VOLUME_IMAGE_SECTION *FvSection;\r
+  EFI_FIRMWARE_VOLUME_HEADER        *PeiMemFv;\r
+  EFI_FIRMWARE_VOLUME_HEADER        *DxeMemFv;\r
 \r
-  NewFvSection = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*) NULL;\r
+  FvSection = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*) NULL;\r
 \r
   Status = FindFfsFileAndSection (\r
              *Fv,\r
@@ -324,8 +359,7 @@ DecompressGuidedFv (
     return Status;\r
   }\r
 \r
-  //PcdGet32 (PcdOvmfMemFvBase), PcdGet32 (PcdOvmfMemFvSize)\r
-  OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdOvmfMemFvBase) + SIZE_1MB);\r
+  OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdOvmfDxeMemFvBase) + SIZE_1MB);\r
   ScratchBuffer = ALIGN_POINTER ((UINT8*) OutputBuffer + OutputBufferSize, SIZE_1MB);\r
   Status = ExtractGuidedSectionDecode (\r
              Section,\r
@@ -338,27 +372,57 @@ DecompressGuidedFv (
     return Status;\r
   }\r
 \r
-  Status = FindFfsSectionInSections (\r
+  Status = FindFfsSectionInstance (\r
+             OutputBuffer,\r
+             OutputBufferSize,\r
+             EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
+             0,\r
+             (EFI_COMMON_SECTION_HEADER**) &FvSection\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "Unable to find PEI FV section\n"));\r
+    return Status;\r
+  }\r
+\r
+  ASSERT (SECTION_SIZE (FvSection) ==\r
+          (PcdGet32 (PcdOvmfPeiMemFvSize) + sizeof (*FvSection)));\r
+  ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);\r
+\r
+  PeiMemFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfPeiMemFvBase);\r
+  CopyMem (PeiMemFv, (VOID*) (FvSection + 1), PcdGet32 (PcdOvmfPeiMemFvSize));\r
+\r
+  if (PeiMemFv->Signature != EFI_FVH_SIGNATURE) {\r
+    DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", PeiMemFv));\r
+    CpuDeadLoop ();\r
+    return EFI_VOLUME_CORRUPTED;\r
+  }\r
+\r
+  Status = FindFfsSectionInstance (\r
              OutputBuffer,\r
              OutputBufferSize,\r
              EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
-             (EFI_COMMON_SECTION_HEADER**) &NewFvSection\r
+             1,\r
+             (EFI_COMMON_SECTION_HEADER**) &FvSection\r
              );\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "Unable to find FV image in extracted data\n"));\r
+    DEBUG ((EFI_D_ERROR, "Unable to find DXE FV section\n"));\r
     return Status;\r
   }\r
 \r
-  NewFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfMemFvBase);\r
-  CopyMem (NewFv, (VOID*) (NewFvSection + 1), PcdGet32 (PcdOvmfMemFvSize));\r
+  ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);\r
+  ASSERT (SECTION_SIZE (FvSection) ==\r
+          (PcdGet32 (PcdOvmfDxeMemFvSize) + sizeof (*FvSection)));\r
+\r
+  DxeMemFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfDxeMemFvBase);\r
+  CopyMem (DxeMemFv, (VOID*) (FvSection + 1), PcdGet32 (PcdOvmfDxeMemFvSize));\r
 \r
-  if (NewFv->Signature != EFI_FVH_SIGNATURE) {\r
-    DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", NewFv));\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
     CpuDeadLoop ();\r
     return EFI_VOLUME_CORRUPTED;\r
   }\r
 \r
-  *Fv = NewFv;\r
+  *Fv = PeiMemFv;\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -374,7 +438,6 @@ DecompressGuidedFv (
 \r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 FindPeiCoreImageBaseInFv (\r
   IN  EFI_FIRMWARE_VOLUME_HEADER       *Fv,\r
   OUT  EFI_PHYSICAL_ADDRESS             *PeiCoreImageBase\r
@@ -406,6 +469,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
@@ -418,7 +525,6 @@ FindPeiCoreImageBaseInFv (
 \r
 **/\r
 VOID\r
-EFIAPI\r
 FindPeiCoreImageBase (\r
   IN OUT  EFI_FIRMWARE_VOLUME_HEADER       **BootFv,\r
      OUT  EFI_PHYSICAL_ADDRESS             *PeiCoreImageBase\r
@@ -426,9 +532,15 @@ FindPeiCoreImageBase (
 {\r
   *PeiCoreImageBase = 0;\r
 \r
-  FindMainFv (BootFv);\r
+  if (IsS3Resume ()) {\r
+    DEBUG ((EFI_D_VERBOSE, "SEC: S3 resume\n"));\r
+    GetS3ResumePeiFv (BootFv);\r
+  } else {\r
+    DEBUG ((EFI_D_VERBOSE, "SEC: Normal boot\n"));\r
+    FindMainFv (BootFv);\r
 \r
-  DecompressGuidedFv (BootFv);\r
+    DecompressMemFvs (BootFv);\r
+  }\r
 \r
   FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);\r
 }\r
@@ -438,7 +550,6 @@ FindPeiCoreImageBase (
 \r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 FindImageBase (\r
   IN  EFI_FIRMWARE_VOLUME_HEADER       *BootFirmwareVolumePtr,\r
   OUT EFI_PHYSICAL_ADDRESS             *SecCoreImageBase\r
@@ -531,7 +642,6 @@ FindImageBase (
 \r
 **/\r
 VOID\r
-EFIAPI\r
 FindAndReportEntryPoints (\r
   IN  EFI_FIRMWARE_VOLUME_HEADER       **BootFirmwareVolumePtr,\r
   OUT EFI_PEI_CORE_ENTRY_POINT         *PeiCoreEntryPoint\r
@@ -590,7 +700,7 @@ SecCoreStartupWithStack (
 \r
   ProcessLibraryConstructorList (NULL, NULL);\r
 \r
-  DEBUG ((EFI_D_ERROR,\r
+  DEBUG ((EFI_D_INFO,\r
     "SecCoreStartupWithStack(0x%x, 0x%x)\n",\r
     (UINT32)(UINTN)BootFv,\r
     (UINT32)(UINTN)TopOfCurrentStack\r
@@ -615,6 +725,14 @@ SecCoreStartupWithStack (
 \r
   AsmWriteIdtr (&IdtDescriptor);\r
 \r
+#if defined (MDE_CPU_X64)\r
+  //\r
+  // ASSERT that the Page Tables were set by the reset vector code to\r
+  // the address we expect.\r
+  //\r
+  ASSERT (AsmReadCr3 () == (UINTN) PcdGet32 (PcdOvmfSecPageTablesBase));\r
+#endif\r
+\r
   //\r
   // |-------------|       <-- TopOfCurrentStack\r
   // |   Stack     | 32k\r
@@ -623,12 +741,16 @@ SecCoreStartupWithStack (
   // |-------------|       <-- SecCoreData.TemporaryRamBase\r
   //\r
 \r
+  ASSERT ((UINTN) (PcdGet32 (PcdOvmfSecPeiTempRamBase) +\r
+                   PcdGet32 (PcdOvmfSecPeiTempRamSize)) ==\r
+          (UINTN) TopOfCurrentStack);\r
+\r
   //\r
   // Initialize SEC hand-off state\r
   //\r
   SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);\r
 \r
-  SecCoreData.TemporaryRamSize       = SIZE_64KB;\r
+  SecCoreData.TemporaryRamSize       = (UINTN) PcdGet32 (PcdOvmfSecPeiTempRamSize);\r
   SecCoreData.TemporaryRamBase       = (VOID*)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);\r
 \r
   SecCoreData.PeiTemporaryRamBase    = SecCoreData.TemporaryRamBase;\r
@@ -713,7 +835,12 @@ TemporaryRamMigration (
   BOOLEAN                          OldStatus;\r
   BASE_LIBRARY_JUMP_BUFFER         JumpBuffer;\r
   \r
-  DEBUG ((EFI_D_ERROR, "TemporaryRamMigration(0x%x, 0x%x, 0x%x)\n", (UINTN)TemporaryMemoryBase, (UINTN)PermanentMemoryBase, CopySize));\r
+  DEBUG ((EFI_D_INFO,\r
+    "TemporaryRamMigration(0x%x, 0x%x, 0x%x)\n",\r
+    (UINTN) TemporaryMemoryBase,\r
+    (UINTN) PermanentMemoryBase,\r
+    CopySize\r
+    ));\r
   \r
   OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;\r
   NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1));\r