]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFspPkg/FspDxeIpl/DxeIpl.c
Add IntelFspPkg to support create FSP bin based on EDKII.
[mirror_edk2.git] / IntelFspPkg / FspDxeIpl / DxeIpl.c
diff --git a/IntelFspPkg/FspDxeIpl/DxeIpl.c b/IntelFspPkg/FspDxeIpl/DxeIpl.c
new file mode 100644 (file)
index 0000000..24e6ef7
--- /dev/null
@@ -0,0 +1,464 @@
+/** @file\r
+\r
+  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "DxeIpl.h"\r
+\r
+\r
+//\r
+// Module Globals used in the DXE to PEI hand off\r
+// These must be module globals, so the stack can be switched\r
+//\r
+CONST EFI_DXE_IPL_PPI mDxeIplPpi = {\r
+  DxeLoadCore\r
+};\r
+\r
+CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomGuidedSectionExtractionPpi = {\r
+  CustomGuidedSectionExtract\r
+};\r
+\r
+CONST EFI_PEI_DECOMPRESS_PPI mDecompressPpi = {\r
+  Decompress\r
+};\r
+\r
+CONST EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {\r
+  {\r
+    EFI_PEI_PPI_DESCRIPTOR_PPI,\r
+    &gEfiDxeIplPpiGuid,\r
+    (VOID *) &mDxeIplPpi\r
+  },\r
+  {\r
+    (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+    &gEfiPeiDecompressPpiGuid,\r
+    (VOID *) &mDecompressPpi\r
+  }\r
+};\r
+\r
+CONST EFI_PEI_PPI_DESCRIPTOR gEndOfPeiSignalPpi = {\r
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+  &gEfiEndOfPeiSignalPpiGuid,\r
+  NULL\r
+};\r
+\r
+/**\r
+  Entry point of DXE IPL PEIM.\r
+\r
+  This function installs DXE IPL PPI and Decompress PPI.  It also reloads\r
+  itself to memory on non-S3 resume boot path.\r
+\r
+  @param[in] FileHandle  Handle of the file being invoked.\r
+  @param[in] PeiServices Describes the list of possible PEI Services.\r
+\r
+  @retval EFI_SUCESS  The entry point of DXE IPL PEIM executes successfully.\r
+  @retval Others      Some error occurs during the execution of this function.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeimInitializeDxeIpl (\r
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,\r
+  IN CONST EFI_PEI_SERVICES     **PeiServices\r
+  )\r
+{\r
+  EFI_STATUS                                Status;\r
+  EFI_GUID                                  *ExtractHandlerGuidTable;\r
+  UINTN                                     ExtractHandlerNumber;\r
+  EFI_PEI_PPI_DESCRIPTOR                    *GuidPpi;\r
+\r
+  //\r
+  // Get custom extract guided section method guid list\r
+  //\r
+  ExtractHandlerNumber = ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable);\r
+\r
+  //\r
+  // Install custom extraction guid PPI\r
+  //\r
+  if (ExtractHandlerNumber > 0) {\r
+    GuidPpi = (EFI_PEI_PPI_DESCRIPTOR *) AllocatePool (ExtractHandlerNumber * sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
+    ASSERT (GuidPpi != NULL);\r
+    while (ExtractHandlerNumber-- > 0) {\r
+      GuidPpi->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;\r
+      GuidPpi->Ppi   = (VOID *) &mCustomGuidedSectionExtractionPpi;\r
+      GuidPpi->Guid  = &ExtractHandlerGuidTable[ExtractHandlerNumber];\r
+      Status = PeiServicesInstallPpi (GuidPpi++);\r
+      ASSERT_EFI_ERROR(Status);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Install DxeIpl and Decompress PPIs.\r
+  //\r
+  Status = PeiServicesInstallPpi (mPpiList);\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  The ExtractSection() function processes the input section and\r
+  returns a pointer to the section contents. If the section being\r
+  extracted does not require processing (if the section\r
+  GuidedSectionHeader.Attributes has the\r
+  EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then\r
+  OutputBuffer is just updated to point to the start of the\r
+  section's contents. Otherwise, *Buffer must be allocated\r
+  from PEI permanent memory.\r
+\r
+  @param[in]  This                   Indicates the\r
+                                     EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.\r
+                                     Buffer containing the input GUIDed section to be\r
+                                     processed. OutputBuffer OutputBuffer is\r
+                                     allocated from PEI permanent memory and contains\r
+                                     the new section stream.\r
+  @param[in]  InputSection           A pointer to the input buffer, which contains\r
+                                     the input section to be processed.\r
+  @param[out] OutputBuffer           A pointer to a caller-allocated buffer, whose\r
+                                     size is specified by the contents of OutputSize.\r
+  @param[out] OutputSize             A pointer to a caller-allocated\r
+                                     UINTN in which the size of *OutputBuffer\r
+                                     allocation is stored. If the function\r
+                                     returns anything other than EFI_SUCCESS,\r
+                                     the value of OutputSize is undefined.\r
+  @param[out] AuthenticationStatus   A pointer to a caller-allocated\r
+                                     UINT32 that indicates the\r
+                                     authentication status of the\r
+                                     output buffer. If the input\r
+                                     section's GuidedSectionHeader.\r
+                                     Attributes field has the\r
+                                     EFI_GUIDED_SECTION_AUTH_STATUS_VALID\r
+                                     bit as clear,\r
+                                     AuthenticationStatus must return\r
+                                     zero. These bits reflect the\r
+                                     status of the extraction\r
+                                     operation. If the function\r
+                                     returns anything other than\r
+                                     EFI_SUCCESS, the value of\r
+                                     AuthenticationStatus is\r
+                                     undefined.\r
+\r
+  @retval EFI_SUCCESS           The InputSection was\r
+                                successfully processed and the\r
+                                section contents were returned.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES  The system has insufficient\r
+                                resources to process the request.\r
+\r
+  @retval EFI_INVALID_PARAMETER The GUID in InputSection does\r
+                                not match this instance of the\r
+                                GUIDed Section Extraction PPI.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CustomGuidedSectionExtract (\r
+  IN CONST  EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,\r
+  IN CONST  VOID                                  *InputSection,\r
+  OUT       VOID                                  **OutputBuffer,\r
+  OUT       UINTN                                 *OutputSize,\r
+  OUT       UINT32                                *AuthenticationStatus\r
+)\r
+{\r
+  EFI_STATUS      Status;\r
+  UINT8           *ScratchBuffer;\r
+  UINT32          ScratchBufferSize;\r
+  UINT32          OutputBufferSize;\r
+  UINT16          SectionAttribute;\r
+\r
+  //\r
+  // Init local variable\r
+  //\r
+  ScratchBuffer = NULL;\r
+\r
+  //\r
+  // Call GetInfo to get the size and attribute of input guided section data.\r
+  //\r
+  Status = ExtractGuidedSectionGetInfo (\r
+             InputSection,\r
+             &OutputBufferSize,\r
+             &ScratchBufferSize,\r
+             &SectionAttribute\r
+             );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  if (ScratchBufferSize != 0) {\r
+    //\r
+    // Allocate scratch buffer\r
+    //\r
+    ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
+    if (ScratchBuffer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+  }\r
+\r
+  if (((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) && OutputBufferSize > 0) {\r
+    //\r
+    // Allocate output buffer\r
+    //\r
+    *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize) + 1);\r
+    if (*OutputBuffer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    DEBUG ((DEBUG_INFO, "Customized Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize, *OutputBuffer));\r
+    //\r
+    // *OutputBuffer still is one section. Adjust *OutputBuffer offset,\r
+    // skip EFI section header to make section data at page alignment.\r
+    //\r
+    *OutputBuffer = (VOID *)((UINT8 *) *OutputBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER));\r
+  }\r
+\r
+  Status = ExtractGuidedSectionDecode (\r
+             InputSection,\r
+             OutputBuffer,\r
+             ScratchBuffer,\r
+             AuthenticationStatus\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Decode failed\r
+    //\r
+    DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  *OutputSize = (UINTN) OutputBufferSize;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+/**\r
+   Decompresses a section to the output buffer.\r
+\r
+   This function looks up the compression type field in the input section and\r
+   applies the appropriate compression algorithm to compress the section to a\r
+   callee allocated buffer.\r
+\r
+   @param[in]  This                  Points to this instance of the\r
+                                     EFI_PEI_DECOMPRESS_PEI PPI.\r
+   @param[in]  CompressionSection    Points to the compressed section.\r
+   @param[out] OutputBuffer          Holds the returned pointer to the decompressed\r
+                                     sections.\r
+   @param[out] OutputSize            Holds the returned size of the decompress\r
+                                     section streams.\r
+\r
+   @retval EFI_SUCCESS           The section was decompressed successfully.\r
+                                 OutputBuffer contains the resulting data and\r
+                                 OutputSize contains the resulting size.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Decompress (\r
+  IN CONST  EFI_PEI_DECOMPRESS_PPI  *This,\r
+  IN CONST  EFI_COMPRESSION_SECTION *CompressionSection,\r
+  OUT       VOID                    **OutputBuffer,\r
+  OUT       UINTN                   *OutputSize\r
+ )\r
+{\r
+  EFI_STATUS                      Status;\r
+  UINT8                           *DstBuffer;\r
+  UINT8                           *ScratchBuffer;\r
+  UINT32                          DstBufferSize;\r
+  UINT32                          ScratchBufferSize;\r
+  VOID                            *CompressionSource;\r
+  UINT32                          CompressionSourceSize;\r
+  UINT32                          UncompressedLength;\r
+  UINT8                           CompressionType;\r
+\r
+  if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {\r
+    ASSERT (FALSE);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (IS_SECTION2 (CompressionSection)) {\r
+    CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION2));\r
+    CompressionSourceSize = (UINT32) (SECTION2_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION2));\r
+    UncompressedLength = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->UncompressedLength;\r
+    CompressionType = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->CompressionType;\r
+  } else {\r
+    CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION));\r
+    CompressionSourceSize = (UINT32) (SECTION_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION));\r
+    UncompressedLength = CompressionSection->UncompressedLength;\r
+    CompressionType = CompressionSection->CompressionType;\r
+  }\r
+\r
+  //\r
+  // This is a compression set, expand it\r
+  //\r
+  switch (CompressionType) {\r
+  case EFI_STANDARD_COMPRESSION:\r
+    if (TRUE) {\r
+      //\r
+      // Load EFI standard compression.\r
+      // For compressed data, decompress them to destination buffer.\r
+      //\r
+      Status = UefiDecompressGetInfo (\r
+                 CompressionSource,\r
+                 CompressionSourceSize,\r
+                 &DstBufferSize,\r
+                 &ScratchBufferSize\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // GetInfo failed\r
+        //\r
+        DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status));\r
+        return EFI_NOT_FOUND;\r
+      }\r
+      //\r
+      // Allocate scratch buffer\r
+      //\r
+      ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
+      if (ScratchBuffer == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+      //\r
+      // Allocate destination buffer, extra one page for adjustment\r
+      //\r
+      DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);\r
+      if (DstBuffer == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+      //\r
+      // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header\r
+      // to make section data at page alignment.\r
+      //\r
+      DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);\r
+      //\r
+      // Call decompress function\r
+      //\r
+      Status = UefiDecompress (\r
+                  CompressionSource,\r
+                  DstBuffer,\r
+                  ScratchBuffer\r
+                  );\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // Decompress failed\r
+        //\r
+        DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status));\r
+        return EFI_NOT_FOUND;\r
+      }\r
+      break;\r
+    } else {\r
+      //\r
+      // PcdDxeIplSupportUefiDecompress is FALSE\r
+      // Don't support UEFI decompression algorithm.\r
+      //\r
+      ASSERT (FALSE);\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+  case EFI_NOT_COMPRESSED:\r
+    //\r
+    // Allocate destination buffer\r
+    //\r
+    DstBufferSize = UncompressedLength;\r
+    DstBuffer     = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);\r
+    if (DstBuffer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    //\r
+    // Adjust DstBuffer offset, skip EFI section header\r
+    // to make section data at page alignment.\r
+    //\r
+    DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);\r
+    //\r
+    // stream is not actually compressed, just encapsulated.  So just copy it.\r
+    //\r
+    CopyMem (DstBuffer, CompressionSource, DstBufferSize);\r
+    break;\r
+\r
+  default:\r
+    //\r
+    // Don't support other unknown compression type.\r
+    //\r
+    ASSERT (FALSE);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  *OutputSize = DstBufferSize;\r
+  *OutputBuffer = DstBuffer;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+   Main entry point to last PEIM.\r
+\r
+   This function finds DXE Core in the firmware volume and transfer the control to\r
+   DXE core.\r
+\r
+   @param[in] This          Entry point for DXE IPL PPI.\r
+   @param[in] PeiServices   General purpose services available to every PEIM.\r
+   @param[in] HobList       Address to the Pei HOB list.\r
+\r
+   @return EFI_SUCCESS              DXE core was successfully loaded.\r
+   @return EFI_OUT_OF_RESOURCES     There are not enough resources to load DXE core.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DxeLoadCore (\r
+  IN CONST EFI_DXE_IPL_PPI *This,\r
+  IN EFI_PEI_SERVICES      **PeiServices,\r
+  IN EFI_PEI_HOB_POINTERS  HobList\r
+  )\r
+{\r
+  EFI_STATUS   Status;\r
+\r
+  DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP HOB is located at 0x%08X\n", HobList));\r
+\r
+  //\r
+  // Give control back to bootloader after FspInit\r
+  //\r
+  DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP is waiting for NOTIFY\n"));\r
+  FspInitDone ();\r
+\r
+  //\r
+  // Bootloader called FSP again through NotifyPhase\r
+  //\r
+  FspWaitForNotify ();\r
+\r
+  //\r
+  // End of PEI phase signal\r
+  //\r
+  Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Give control back to the boot loader framework caller\r
+  //\r
+  DEBUG ((DEBUG_INFO | DEBUG_INIT,   "============= PEIM FSP is Completed =============\n\n"));\r
+\r
+  SetFspApiReturnStatus(EFI_SUCCESS);\r
+\r
+  SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_RDYBOOT_EXIT);\r
+\r
+  Pei2LoaderSwitchStack();\r
+\r
+  //\r
+  // Should not come here\r
+  //\r
+  while (TRUE) {\r
+    DEBUG ((DEBUG_ERROR, "No FSP API should be called after FSP is DONE!\n"));\r
+    SetFspApiReturnStatus(EFI_UNSUPPORTED);\r
+    Pei2LoaderSwitchStack();\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r