]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Pei/Ppi/Ppi.c
MdeModulePkg/PeiCore: Enable T-RAM evacuation in PeiCore (CVE-2019-11098)
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Ppi / Ppi.c
index 1ffe718c470205f80ace88dbeeb401ac42335520..541047d98a4a1423baa7a782e136ec403db109d5 100644 (file)
@@ -198,6 +198,227 @@ ConvertPpiPointers (
   }\r
 }\r
 \r
+/**\r
+\r
+  Migrate Notify Pointers inside an FV from temporary memory to permanent memory.\r
+\r
+  @param PrivateData      Pointer to PeiCore's private data structure.\r
+  @param OrgFvHandle      Address of FV Handle in temporary memory.\r
+  @param FvHandle         Address of FV Handle in permanent memory.\r
+  @param FvSize           Size of the FV.\r
+\r
+**/\r
+VOID\r
+ConvertPpiPointersFv (\r
+  IN  PEI_CORE_INSTANCE       *PrivateData,\r
+  IN  UINTN                   OrgFvHandle,\r
+  IN  UINTN                   FvHandle,\r
+  IN  UINTN                   FvSize\r
+  )\r
+{\r
+  UINT8                             Index;\r
+  UINTN                             Offset;\r
+  BOOLEAN                           OffsetPositive;\r
+  EFI_PEI_FIRMWARE_VOLUME_INFO_PPI  *FvInfoPpi;\r
+  UINT8                             GuidIndex;\r
+  EFI_GUID                          *Guid;\r
+  EFI_GUID                          *GuidCheckList[2];\r
+\r
+  GuidCheckList[0] = &gEfiPeiFirmwareVolumeInfoPpiGuid;\r
+  GuidCheckList[1] = &gEfiPeiFirmwareVolumeInfo2PpiGuid;\r
+\r
+  if (FvHandle > OrgFvHandle) {\r
+    OffsetPositive = TRUE;\r
+    Offset = FvHandle - OrgFvHandle;\r
+  } else {\r
+    OffsetPositive = FALSE;\r
+    Offset = OrgFvHandle - FvHandle;\r
+  }\r
+\r
+  DEBUG ((DEBUG_VERBOSE, "Converting PPI pointers in FV.\n"));\r
+  DEBUG ((\r
+    DEBUG_VERBOSE,\r
+    "  OrgFvHandle at 0x%08x. FvHandle at 0x%08x. FvSize = 0x%x\n",\r
+    (UINTN) OrgFvHandle,\r
+    (UINTN) FvHandle,\r
+    FvSize\r
+    ));\r
+  DEBUG ((\r
+    DEBUG_VERBOSE,\r
+    "    OrgFvHandle range: 0x%08x - 0x%08x\n",\r
+    OrgFvHandle,\r
+    OrgFvHandle + FvSize\r
+    ));\r
+\r
+  for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {\r
+      ConvertPointer (\r
+        (VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw,\r
+        OrgFvHandle,\r
+        OrgFvHandle + FvSize,\r
+        Offset,\r
+        OffsetPositive\r
+        );\r
+      ConvertPointer (\r
+        (VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid,\r
+        OrgFvHandle,\r
+        OrgFvHandle + FvSize,\r
+        Offset,\r
+        OffsetPositive\r
+        );\r
+      ConvertPointer (\r
+        (VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Notify,\r
+        OrgFvHandle,\r
+        OrgFvHandle + FvSize,\r
+        Offset,\r
+        OffsetPositive\r
+        );\r
+  }\r
+\r
+  for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {\r
+    ConvertPointer (\r
+      (VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw,\r
+      OrgFvHandle,\r
+      OrgFvHandle + FvSize,\r
+      Offset,\r
+      OffsetPositive\r
+      );\r
+    ConvertPointer (\r
+      (VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid,\r
+      OrgFvHandle,\r
+      OrgFvHandle + FvSize,\r
+      Offset,\r
+      OffsetPositive\r
+      );\r
+    ConvertPointer (\r
+      (VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Notify,\r
+      OrgFvHandle,\r
+      OrgFvHandle + FvSize,\r
+      Offset,\r
+      OffsetPositive\r
+      );\r
+  }\r
+\r
+  for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {\r
+    ConvertPointer (\r
+      (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw,\r
+      OrgFvHandle,\r
+      OrgFvHandle + FvSize,\r
+      Offset,\r
+      OffsetPositive\r
+      );\r
+    ConvertPointer (\r
+      (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid,\r
+      OrgFvHandle,\r
+      OrgFvHandle + FvSize,\r
+      Offset,\r
+      OffsetPositive\r
+      );\r
+    ConvertPointer (\r
+      (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi,\r
+      OrgFvHandle,\r
+      OrgFvHandle + FvSize,\r
+      Offset,\r
+      OffsetPositive\r
+      );\r
+\r
+    Guid = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid;\r
+    for (GuidIndex = 0; GuidIndex < ARRAY_SIZE (GuidCheckList); ++GuidIndex) {\r
+      //\r
+      // Don't use CompareGuid function here for performance reasons.\r
+      // Instead we compare the GUID as INT32 at a time and branch\r
+      // on the first failed comparison.\r
+      //\r
+      if ((((INT32 *)Guid)[0] == ((INT32 *)GuidCheckList[GuidIndex])[0]) &&\r
+          (((INT32 *)Guid)[1] == ((INT32 *)GuidCheckList[GuidIndex])[1]) &&\r
+          (((INT32 *)Guid)[2] == ((INT32 *)GuidCheckList[GuidIndex])[2]) &&\r
+          (((INT32 *)Guid)[3] == ((INT32 *)GuidCheckList[GuidIndex])[3])) {\r
+        FvInfoPpi = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi;\r
+        DEBUG ((DEBUG_VERBOSE, "      FvInfo: %p -> ", FvInfoPpi->FvInfo));\r
+        if ((UINTN)FvInfoPpi->FvInfo == OrgFvHandle) {\r
+          ConvertPointer (\r
+            (VOID **)&FvInfoPpi->FvInfo,\r
+            OrgFvHandle,\r
+            OrgFvHandle + FvSize,\r
+            Offset,\r
+            OffsetPositive\r
+            );\r
+          DEBUG ((DEBUG_VERBOSE, "%p", FvInfoPpi->FvInfo));\r
+        }\r
+        DEBUG ((DEBUG_VERBOSE, "\n"));\r
+        break;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+\r
+  Dumps the PPI lists to debug output.\r
+\r
+  @param PrivateData     Points to PeiCore's private instance data.\r
+\r
+**/\r
+VOID\r
+DumpPpiList (\r
+  IN PEI_CORE_INSTANCE    *PrivateData\r
+  )\r
+{\r
+  DEBUG_CODE_BEGIN ();\r
+  UINTN   Index;\r
+\r
+  if (PrivateData == NULL) {\r
+    return;\r
+  }\r
+\r
+  for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {\r
+    DEBUG ((\r
+      DEBUG_VERBOSE,\r
+      "CallbackNotify[%2d] {%g} at 0x%x (%a)\n",\r
+      Index,\r
+      PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid,\r
+      (UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw,\r
+      (\r
+        !(\r
+          ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) &&\r
+          (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)\r
+          )\r
+        ? "CAR" : "Post-Memory"\r
+        )\r
+      ));\r
+  }\r
+  for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {\r
+    DEBUG ((DEBUG_VERBOSE,\r
+    "DispatchNotify[%2d] {%g} at 0x%x (%a)\n",\r
+    Index,\r
+    PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid,\r
+    (UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw,\r
+    (\r
+      !(\r
+        ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw >=PrivateData->PhysicalMemoryBegin) &&\r
+        (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)\r
+        )\r
+      ? "CAR" : "Post-Memory"\r
+      )\r
+    ));\r
+  }\r
+  for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {\r
+    DEBUG ((DEBUG_VERBOSE,\r
+    "PPI[%2d] {%g} at 0x%x (%a)\n",\r
+    Index,\r
+    PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid,\r
+    (UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw,\r
+    (\r
+      !(\r
+        ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) &&\r
+        (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw) + sizeof (EFI_PEI_PPI_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)\r
+        )\r
+      ? "CAR" : "Post-Memory"\r
+      )\r
+    ));\r
+  }\r
+  DEBUG_CODE_END ();\r
+}\r
+\r
 /**\r
 \r
   This function installs an interface in the PEI PPI database by GUID.\r
@@ -830,3 +1051,68 @@ ProcessPpiListFromSec (
   }\r
 }\r
 \r
+/**\r
+\r
+  Migrate PPI Pointers of PEI_CORE from temporary memory to permanent memory.\r
+\r
+  @param PrivateData      Pointer to PeiCore's private data structure.\r
+  @param CoreFvHandle     Address of PEI_CORE FV Handle in temporary memory.\r
+\r
+**/\r
+VOID\r
+ConvertPeiCorePpiPointers (\r
+  IN  PEI_CORE_INSTANCE        *PrivateData,\r
+  PEI_CORE_FV_HANDLE           CoreFvHandle\r
+  )\r
+{\r
+  EFI_FV_FILE_INFO      FileInfo;\r
+  EFI_PHYSICAL_ADDRESS  OrgImageBase;\r
+  EFI_PHYSICAL_ADDRESS  MigratedImageBase;\r
+  UINTN                 PeiCoreModuleSize;\r
+  EFI_PEI_FILE_HANDLE   PeiCoreFileHandle;\r
+  VOID                  *PeiCoreImageBase;\r
+  VOID                  *PeiCoreEntryPoint;\r
+  EFI_STATUS            Status;\r
+\r
+  PeiCoreFileHandle = NULL;\r
+\r
+  //\r
+  // Find the PEI Core in the BFV in temporary memory.\r
+  //\r
+  Status =  CoreFvHandle.FvPpi->FindFileByType (\r
+                                  CoreFvHandle.FvPpi,\r
+                                  EFI_FV_FILETYPE_PEI_CORE,\r
+                                  CoreFvHandle.FvHandle,\r
+                                  &PeiCoreFileHandle\r
+                                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = CoreFvHandle.FvPpi->GetFileInfo (CoreFvHandle.FvPpi, PeiCoreFileHandle, &FileInfo);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    Status = PeiGetPe32Data (PeiCoreFileHandle, &PeiCoreImageBase);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    //\r
+    // Find PEI Core EntryPoint in the BFV in temporary memory.\r
+    //\r
+    Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase,  &PeiCoreEntryPoint);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    OrgImageBase = (UINTN) PeiCoreImageBase;\r
+    MigratedImageBase = (UINTN) _ModuleEntryPoint - ((UINTN) PeiCoreEntryPoint - (UINTN) PeiCoreImageBase);\r
+\r
+    //\r
+    // Size of loaded PEI_CORE in permanent memory.\r
+    //\r
+    PeiCoreModuleSize = (UINTN)FileInfo.BufferSize - ((UINTN) OrgImageBase - (UINTN) FileInfo.Buffer);\r
+\r
+    //\r
+    // Migrate PEI_CORE PPI pointers from temporary memory to newly\r
+    // installed PEI_CORE in permanent memory.\r
+    //\r
+    ConvertPpiPointersFv (PrivateData, (UINTN) OrgImageBase, (UINTN) MigratedImageBase, PeiCoreModuleSize);\r
+  }\r
+}\r
+\r