]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c
IntelFramdworkModulePkg/LegacyBios: Add IoMmu Support.
[mirror_edk2.git] / IntelFrameworkModulePkg / Csm / LegacyBiosDxe / LegacyPci.c
index 62d0feed3c9b28cab526fbdd4b77e959e27fc165..8ffdf0c1ff9551ad06f0bc8070b3d26243d3b442 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
 \r
-Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2017, 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\r
@@ -41,7 +41,7 @@ BOOLEAN                             mIgnoreBbsUpdateFlag;
 BOOLEAN                             mVgaInstallationInProgress  = FALSE;\r
 UINT32                              mRomCount                   = 0x00;\r
 ROM_INSTANCE_ENTRY                  mRomEntry[ROM_MAX_ENTRIES];\r
-\r
+EDKII_IOMMU_PROTOCOL                *mIoMmu;\r
 \r
 /**\r
   Query shadowed legacy ROM parameters registered by RomShadow() previously.\r
@@ -318,7 +318,7 @@ GetPciLegacyRom (
       break;\r
     }\r
 \r
-    if ((UINTN)(RomHeader.Raw - (UINT8 *) *Rom) + Pcir->ImageLength * 512 > *ImageSize) {\r
+    if (((UINTN)RomHeader.Raw - (UINTN)*Rom) + Pcir->ImageLength * 512 > *ImageSize) {\r
       break;\r
     }\r
     \r
@@ -1198,7 +1198,7 @@ PciProgramAllInterruptLineRegisters (
                       &Supports\r
                       );\r
     if (!EFI_ERROR (Status)) {\r
-      Supports &= EFI_PCI_DEVICE_ENABLE;\r
+      Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;\r
       Status = PciIo->Attributes (\r
                         PciIo,\r
                         EfiPciIoAttributeOperationEnable,\r
@@ -1772,7 +1772,7 @@ PciShadowRoms (
                           &Supports\r
                           );\r
         if (!EFI_ERROR (Status)) {\r
-          Supports &= EFI_PCI_DEVICE_ENABLE;\r
+          Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;\r
           Status = PciIo->Attributes (\r
                             PciIo,\r
                             EfiPciIoAttributeOperationEnable,\r
@@ -1812,7 +1812,7 @@ PciShadowRoms (
   @param  RomSize                Size of ROM Image\r
   @param  Flags                  Indicates if ROM found and if PC-AT.\r
 \r
-  @retval EFI_SUCCESS            Legacy Option ROM availible for this device\r
+  @retval EFI_SUCCESS            Legacy Option ROM available for this device\r
   @retval EFI_UNSUPPORTED        Legacy Option ROM not supported.\r
 \r
 **/\r
@@ -1854,7 +1854,7 @@ LegacyBiosCheckPciRom (
     @param[out] OpromRevision          Revision of the PCI Rom\r
     @param[out] ConfigUtilityCodeHeaderPointer of Configuration Utility Code Header\r
 \r
-    @return EFI_SUCCESS            Legacy Option ROM availible for this device\r
+    @return EFI_SUCCESS            Legacy Option ROM available for this device\r
     @return EFI_ALREADY_STARTED    This device is already managed by its Oprom\r
     @return EFI_UNSUPPORTED        Legacy Option ROM not supported.\r
 \r
@@ -1879,6 +1879,7 @@ LegacyBiosCheckPciRomEx (
   PCI_TYPE00                      PciConfigHeader;\r
   VOID                            *LocalConfigUtilityCodeHeader;\r
 \r
+  LocalConfigUtilityCodeHeader = NULL;\r
   *Flags = NO_ROM;\r
   Status = gBS->HandleProtocol (\r
                   PciHandle,\r
@@ -1894,7 +1895,7 @@ LegacyBiosCheckPciRomEx (
   //\r
   Status = IsLegacyRom (PciHandle);\r
   if (!EFI_ERROR (Status)) {\r
-    *Flags |= (ROM_FOUND | VALID_LEGACY_ROM);\r
+    *Flags |= (UINTN)(ROM_FOUND | VALID_LEGACY_ROM);\r
     return EFI_SUCCESS;\r
   }\r
   //\r
@@ -2186,8 +2187,8 @@ LegacyBiosInstallVgaRom (
                     &Supports\r
                     );\r
   if (!EFI_ERROR (Status)) {\r
-    Supports &= EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | \\r
-                EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16;\r
+    Supports &= (UINT64)(EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | \\r
+                         EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);\r
     Status = PciIo->Attributes (\r
                       PciIo,\r
                       EfiPciIoAttributeOperationEnable,\r
@@ -2283,6 +2284,7 @@ LegacyBiosInstallRom (
   UINT32                LocalTime;\r
   UINT32                StartBbsIndex;\r
   UINT32                EndBbsIndex;\r
+  UINT32                MaxRomAddr;\r
   UINTN                 TempData;\r
   UINTN                 InitAddress;\r
   UINTN                 RuntimeAddress;\r
@@ -2298,6 +2300,15 @@ LegacyBiosInstallRom (
   Function        = 0;\r
   VideoMode       = 0;\r
   PhysicalAddress = 0;\r
+  MaxRomAddr      = PcdGet32 (PcdEndOpromShadowAddress);\r
+\r
+  if ((Private->Legacy16Table->TableLength >= OFFSET_OF(EFI_COMPATIBILITY16_TABLE, HiPermanentMemoryAddress)) &&\r
+      (Private->Legacy16Table->UmaAddress != 0) && \r
+      (Private->Legacy16Table->UmaSize != 0) &&\r
+      (MaxRomAddr > (Private->Legacy16Table->UmaAddress))) {\r
+    MaxRomAddr = Private->Legacy16Table->UmaAddress;\r
+  }\r
+\r
 \r
   PciProgramAllInterruptLineRegisters (Private);\r
 \r
@@ -2330,7 +2341,7 @@ LegacyBiosInstallRom (
     //   then test if there is enough space for its RT code\r
     //\r
     RuntimeAddress = Private->OptionRom;\r
-    if (RuntimeAddress + *RuntimeImageLength > PcdGet32 (PcdEndOpromShadowAddress)) {\r
+    if (RuntimeAddress + *RuntimeImageLength > MaxRomAddr) {\r
       DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__));\r
       gBS->FreePages (PhysicalAddress, EFI_SIZE_TO_PAGES (ImageSize));\r
       //\r
@@ -2348,7 +2359,7 @@ LegacyBiosInstallRom (
     //   test if there is enough space for its INIT code\r
     //\r
     InitAddress    = PCI_START_ADDRESS (Private->OptionRom);\r
-    if (InitAddress + ImageSize > PcdGet32 (PcdEndOpromShadowAddress)) {\r
+    if (InitAddress + ImageSize > MaxRomAddr) {\r
       DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__));\r
       //\r
       // Report Status Code to indicate that there is no enough space for OpROM\r
@@ -2685,6 +2696,61 @@ Done:
   return Status;\r
 }\r
 \r
+/**\r
+  Let IOMMU grant DMA access for the PCI device.\r
+\r
+  @param  PciHandle             The EFI handle for the PCI device.\r
+  @param  HostAddress           The system memory address to map to the PCI controller.\r
+  @param  NumberOfBytes         The number of bytes to map.\r
+\r
+  @retval EFI_SUCCESS  The DMA access is granted.\r
+**/\r
+EFI_STATUS\r
+IoMmuGrantAccess (\r
+  IN  EFI_HANDLE                        PciHandle,\r
+  IN  EFI_PHYSICAL_ADDRESS              HostAddress,\r
+  IN  UINTN                             NumberOfBytes\r
+  )\r
+{\r
+  EFI_PHYSICAL_ADDRESS            DeviceAddress;\r
+  VOID                            *Mapping;\r
+  EFI_STATUS                      Status;\r
+\r
+  if (PciHandle == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+  if (mIoMmu == NULL) {\r
+    gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmu);\r
+  }\r
+  if (mIoMmu != NULL) {\r
+    Status = mIoMmu->Map (\r
+                       mIoMmu,\r
+                       EdkiiIoMmuOperationBusMasterCommonBuffer,\r
+                       (VOID *)(UINTN)HostAddress,\r
+                       &NumberOfBytes,\r
+                       &DeviceAddress,\r
+                       &Mapping\r
+                       );\r
+    if (EFI_ERROR(Status)) {\r
+      DEBUG ((DEBUG_ERROR, "LegacyPci - IoMmuMap - %r\n", Status));\r
+    } else {\r
+      ASSERT (DeviceAddress == HostAddress);\r
+      Status = mIoMmu->SetAttribute (\r
+                         mIoMmu,\r
+                         PciHandle,\r
+                         Mapping,\r
+                         EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE\r
+                         );\r
+      if (EFI_ERROR(Status)) {\r
+        DEBUG ((DEBUG_ERROR, "LegacyPci - IoMmuSetAttribute - %r\n", Status));\r
+      }\r
+    }\r
+  }\r
+  return Status;\r
+}\r
+\r
 /**\r
   Load a legacy PC-AT OPROM on the PciHandle device. Return information\r
   about how many disks were added by the OPROM and the shadow address and\r
@@ -2914,7 +2980,15 @@ LegacyBiosInstallPciRom (
       return EFI_UNSUPPORTED;\r
     }\r
 \r
-    if (!Private->VgaInstalled) {\r
+    Status = Private->LegacyBiosPlatform->GetPlatformHandle (\r
+                                            Private->LegacyBiosPlatform,\r
+                                            EfiGetPlatformVgaHandle,\r
+                                            0,\r
+                                            &HandleBuffer,\r
+                                            &HandleCount,\r
+                                            NULL\r
+                                            );\r
+    if ((!EFI_ERROR (Status)) && (!Private->VgaInstalled)) {\r
       //\r
       // A return status of EFI_NOT_FOUND is considered valid (No EFI\r
       // driver is controlling video.\r
@@ -2959,6 +3033,21 @@ LegacyBiosInstallPciRom (
       RuntimeImageLength = Pcir->MaxRuntimeImageLength * 512;\r
     }\r
   }\r
+\r
+  //\r
+  // Grant access for below 1M\r
+  // BDA/EBDA/LowPMM and scratch memory for OPROM.\r
+  //\r
+  IoMmuGrantAccess (PciHandle, 0, SIZE_1MB);\r
+  //\r
+  // Grant access for HiPmm\r
+  //\r
+  IoMmuGrantAccess (\r
+    PciHandle,\r
+    Private->IntThunk->EfiToLegacy16InitTable.HiPmmMemory,\r
+    Private->IntThunk->EfiToLegacy16InitTable.HiPmmMemorySizeInBytes\r
+    );\r
+\r
   //\r
   // Shadow and initialize the OpROM.\r
   //\r