]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkModulePkg/Core/DxeIplX64Peim/DxeLoadX64.c
Use global variable gInMemory in place of gInMemoryGuid ppi in DxeIplX64 module to...
[mirror_edk2.git] / EdkModulePkg / Core / DxeIplX64Peim / DxeLoadX64.c
index d01daafbe2deace2d88a7e154f2b06f6f6d81b1a..57ffb28f4ae00ea2b8f5cbe1fb1540237e369e62 100644 (file)
@@ -22,7 +22,9 @@ Abstract:
 \r
 #include <DxeIpl.h>\r
 \r
+#ifndef __GNUC__\r
 #pragma warning( disable : 4305 )\r
+#endif\r
 \r
 BOOLEAN gInMemory = FALSE;\r
 \r
@@ -50,12 +52,6 @@ static EFI_PEI_PPI_DESCRIPTOR     mPpiList = {
   &mDxeIplPpi\r
 };\r
 \r
-static EFI_PEI_PPI_DESCRIPTOR     mPpiPeiInMemory = {\r
-  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
-  &gPeiInMemoryGuid,\r
-  NULL\r
-};\r
-\r
 static EFI_PEI_PPI_DESCRIPTOR     mPpiSignal = {\r
   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
   &gEfiEndOfPeiSignalPpiGuid,\r
@@ -125,14 +121,7 @@ Returns:
 \r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  Status = PeiServicesLocatePpi (\r
-             &gPeiInMemoryGuid,\r
-             0,\r
-             NULL,\r
-             NULL\r
-             );\r
-\r
-  if (EFI_ERROR (Status) && (BootMode != BOOT_ON_S3_RESUME)) {   \r
+  if (!gInMemory && (BootMode != BOOT_ON_S3_RESUME)) {   \r
     //\r
     // The DxeIpl has not yet been shadowed\r
     //\r
@@ -148,10 +137,6 @@ Returns:
 \r
   } else {\r
     if (BootMode != BOOT_ON_S3_RESUME) {\r
-    //\r
-    // The DxeIpl has been shadowed\r
-    //\r
-    gInMemory = TRUE;\r
 \r
     //\r
     // Install LoadFile PPI\r
@@ -165,7 +150,7 @@ Returns:
     //\r
     // Install DxeIpl PPI\r
     //\r
-    PeiServicesInstallPpi (&mPpiList);\r
+    Status = PeiServicesInstallPpi (&mPpiList);\r
 \r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
@@ -207,7 +192,9 @@ Returns:
   EFI_PHYSICAL_ADDRESS                                      BaseOfStack;\r
   EFI_PHYSICAL_ADDRESS                                      BspStore;\r
   EFI_GUID                                                  DxeCoreFileName;\r
+  EFI_GUID                                                  FirmwareFileName;\r
   VOID                                                      *DxeCorePe32Data;\r
+  VOID                                                      *FvImageData;     \r
   EFI_PHYSICAL_ADDRESS                                      DxeCoreAddress;\r
   UINT64                                                    DxeCoreSize;\r
   EFI_PHYSICAL_ADDRESS                                      DxeCoreEntryPoint;\r
@@ -257,11 +244,21 @@ Returns:
   ASSERT (BaseOfStack != 0);\r
 \r
   //\r
-  // Compute the top of the stack we were allocated. Pre-allocate a 32 bytes\r
-  // for safety (PpisNeededByDxe and DxeCore).\r
+  // Compute the top of the stack we were allocated, which is used to load X64 dxe core. \r
+  // Pre-allocate a 32 bytes which confroms to x64 calling convention.\r
+  //\r
+  // The first four parameters to a function are passed in rcx, rdx, r8 and r9. \r
+  // Any further parameters are pushed on the stack. Furthermore, space (4 * 8bytes) for the \r
+  // register parameters is reserved on the stack, in case the called function \r
+  // wants to spill them; this is important if the function is variadic. \r
   //\r
   TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32;\r
 \r
+  //\r
+  //  X64 Calling Conventions requires that the stack must be aligned to 16 bytes\r
+  //\r
+  TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, 16);\r
+\r
   //\r
   // Add architecture-specifc HOBs (including the BspStore HOB)\r
   //\r
@@ -288,6 +285,18 @@ Returns:
     }\r
   }\r
 \r
+  //\r
+  // Find the EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE type compressed Firmware Volume file\r
+  // The file found will be processed by PeiProcessFile: It will first be decompressed to\r
+  // a normal FV, then a corresponding FV type hob will be built. \r
+  //\r
+  Status = PeiFindFile (\r
+            EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,\r
+            EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
+            &FirmwareFileName,\r
+            &FvImageData\r
+            );\r
+\r
   //\r
   // Find the DXE Core in a Firmware Volume\r
   //\r
@@ -300,8 +309,9 @@ Returns:
   ASSERT_EFI_ERROR (Status);\r
 \r
   //\r
-  // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA \\r
+  // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA\r
   // memory, it may be corrupted when copying FV to high-end memory \r
+  //\r
   LoadGo64Gdt();\r
 \r
   //\r
@@ -418,10 +428,11 @@ Returns:
   FwVolHeader   = NULL;\r
   FfsFileHeader = NULL;\r
   SectionData   = NULL;\r
+  Status        = EFI_SUCCESS;\r
 \r
   //\r
-  // Foreach Firmware Volume, look for a specified type\r
-  // of file and break out when one is found\r
+  // For each Firmware Volume, look for a specified type\r
+  // of file and break out until no one is found \r
   //\r
   Hob.Raw = GetHobList ();\r
   while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw)) != NULL) {\r
@@ -434,11 +445,14 @@ Returns:
     if (!EFI_ERROR (Status)) {\r
       Status = PeiProcessFile (\r
                  SectionType,\r
-                 &FfsFileHeader,\r
-                 Pe32Data\r
+                 FfsFileHeader,\r
+                 Pe32Data,\r
+                 &Hob\r
                  );\r
       CopyMem (FileName, &FfsFileHeader->Name, sizeof (EFI_GUID));\r
-      return Status;\r
+      if (!EFI_ERROR (Status)) {\r
+        return EFI_SUCCESS;\r
+      }\r
     }\r
     Hob.Raw = GET_NEXT_HOB (Hob);\r
   }\r
@@ -589,14 +603,9 @@ Returns:
  \r
   if (Status == EFI_SUCCESS) {\r
     //\r
-    // Install PeiInMemory to indicate the Dxeipl is shadowed\r
+    // Set gInMemory global variable to TRUE to indicate the dxeipl is shadowed.\r
     //\r
-    Status = PeiServicesInstallPpi (&mPpiPeiInMemory);\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
-\r
+    *(BOOLEAN *) ((UINTN) &gInMemory + (UINTN) DxeIplEntryPoint - (UINTN) _ModuleEntryPoint) = TRUE;\r
     Status = ((EFI_PEIM_ENTRY_POINT) (UINTN) DxeIplEntryPoint) (DxeIplFileHeader, GetPeiServicesTablePointer());\r
   }\r
 \r
@@ -649,8 +658,9 @@ Returns:
   //\r
   Status = PeiProcessFile (\r
             EFI_SECTION_PE32,\r
-            &FfsHeader,\r
-            &Pe32Data\r
+            FfsHeader,\r
+            &Pe32Data,\r
+            NULL\r
             );\r
 \r
   if (EFI_ERROR (Status)) {\r
@@ -674,8 +684,9 @@ Returns:
 EFI_STATUS\r
 PeiProcessFile (\r
   IN      UINT16                 SectionType,\r
-  IN OUT  EFI_FFS_FILE_HEADER    **RealFfsFileHeader,\r
-  OUT     VOID                   **Pe32Data\r
+  IN      EFI_FFS_FILE_HEADER    *FfsFileHeader,\r
+  OUT     VOID                   **Pe32Data,\r
+  IN      EFI_PEI_HOB_POINTERS   *OrigHob\r
   )\r
 /*++\r
 \r
@@ -723,9 +734,7 @@ Returns:
   EFI_GUID                        TempGuid;\r
   EFI_FIRMWARE_VOLUME_HEADER      *FvHeader;\r
   EFI_COMPRESSION_SECTION         *CompressionSection;\r
-  EFI_FFS_FILE_HEADER             *FfsFileHeader;\r
-  \r
-  FfsFileHeader = *RealFfsFileHeader;\r
+  UINT32                          FvAlignment;\r
 \r
   Status = PeiServicesFfsFindSectionData (\r
              EFI_SECTION_COMPRESSION,\r
@@ -734,7 +743,7 @@ Returns:
              );\r
 \r
   //\r
-  // Upon finding a DXE Core file, see if there is first a compression section\r
+  // First process the compression section\r
   //\r
   if (!EFI_ERROR (Status)) {\r
     //\r
@@ -910,31 +919,64 @@ Returns:
                     );\r
 \r
         CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer;\r
-        if (CmpSection->Type == EFI_SECTION_RAW) {\r
+        if (CmpSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) {\r
+          // \r
+          // Firmware Volume Image in this Section\r
+          // Skip the section header to get FvHeader\r
           //\r
-          // Skip the section header and\r
-          // adjust the pointer alignment to 16\r
-          //\r
-          FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (DstBuffer + 16);\r
+          FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (CmpSection + 1);\r
 \r
-          if (FvHeader->Signature == EFI_FVH_SIGNATURE) {\r
-            FfsFileHeader = NULL;\r
+          if (FvHeader->Signature == EFI_FVH_SIGNATURE) {            \r
+            //\r
+            // Adjust Fv Base Address Alignment based on Align Attributes in Fv Header\r
+            //\r
+            \r
+            //\r
+            // When FvImage support Alignment, we need to check whether \r
+            // its alignment is correct. \r
+            //\r
+            if (FvHeader->Attributes | EFI_FVB_ALIGNMENT_CAP) {\r
+              \r
+              //\r
+              // Calculate the mini alignment for this FvImage\r
+              //\r
+              FvAlignment = 1 << (LowBitSet32 (FvHeader->Attributes >> 16) + 1);\r
+              \r
+              //\r
+              // If current FvImage base address doesn't meet the its alignment,\r
+              // we need to reload this FvImage to another correct memory address.\r
+              //\r
+              if (((UINTN) FvHeader % FvAlignment) != 0) {\r
+                DstBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength), FvAlignment);\r
+                if (DstBuffer == NULL) {\r
+                  return EFI_OUT_OF_RESOURCES;\r
+                }\r
+                CopyMem (DstBuffer, FvHeader, (UINTN) FvHeader->FvLength);\r
+                FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DstBuffer;  \r
+              }\r
+            }\r
+            //\r
+            // Build new FvHob for new decompressed Fv image.\r
+            //\r
             BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, FvHeader->FvLength);\r
-            Status = PeiServicesFfsFindNextFile (\r
-                       EFI_FV_FILETYPE_DXE_CORE,\r
-                       FvHeader,\r
-                       &FfsFileHeader\r
-                       );\r
-\r
-            if (EFI_ERROR (Status)) {\r
-              return EFI_NOT_FOUND;\r
+            \r
+            //\r
+            // Set the original FvHob to unused.\r
+            //\r
+            if (OrigHob != NULL) {\r
+              OrigHob->Header->HobType = EFI_HOB_TYPE_UNUSED;\r
             }\r
-\r
+            \r
             //\r
-            // Reture the FfsHeader that contain Pe32Data.\r
+            // when search FvImage Section return true.\r
             //\r
-            *RealFfsFileHeader = FfsFileHeader;\r
-            return PeiProcessFile (SectionType, RealFfsFileHeader, Pe32Data);\r
+            if (SectionType == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) {\r
+              *Pe32Data = (VOID *) FvHeader;\r
+              return EFI_SUCCESS;\r
+            } else {\r
+              return EFI_NOT_FOUND;\r
+            }\r
+\r
           }\r
         }\r
         //\r
@@ -957,6 +999,9 @@ Returns:
           CmpSection                = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) CmpSection + OccupiedCmpSectionLength);\r
         } while (CmpSection->Type != 0 && (UINTN) ((UINT8 *) CmpSection - (UINT8 *) CmpFileData) < CmpFileSize);\r
       }\r
+      //\r
+      // End of the decompression activity\r
+      //\r
 \r
       Section   = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);\r
       FileSize  = FfsFileHeader->Size[0] & 0xFF;\r
@@ -964,11 +1009,17 @@ Returns:
       FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000;\r
       FileSize &= 0x00FFFFFF;\r
     } while (Section->Type != 0 && (UINTN) ((UINT8 *) Section - (UINT8 *) FfsFileHeader) < FileSize);\r
-\r
+    \r
     //\r
-    // End of the decompression activity\r
+    // search all sections (compression and non compression) in this FFS, don't \r
+    // find expected section.\r
     //\r
+    return EFI_NOT_FOUND;\r
   } else {\r
+    //\r
+    // For those FFS that doesn't contain compression section, directly search \r
+    // PE or TE section in this FFS.\r
+    //\r
 \r
     Status = PeiServicesFfsFindSectionData (\r
                EFI_SECTION_PE32,\r
@@ -991,4 +1042,5 @@ Returns:
   *Pe32Data = SectionData;\r
 \r
   return EFI_SUCCESS;\r
-}
\ No newline at end of file
+}\r
+\r