]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c
MdeModulePkg/Pci: Add DeviceSecurity support.
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciHotPlugSupport.c
index ca8766869ae7aaf87878e9799a0c31f5e9653bb8..0dc8ec23b0527296931473d27676b52c33ee94a4 100644 (file)
@@ -1,14 +1,8 @@
 /** @file\r
   PCI Hot Plug support functions implementation for PCI Bus module..\r
 \r
-Copyright (c) 2006 - 2010, 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
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -41,7 +35,7 @@ PciHPCInitialized (
 }\r
 \r
 /**\r
-  Compare two device pathes to check if they are exactly same.\r
+  Compare two device paths to check if they are exactly same.\r
 \r
   @param DevicePath1    A pointer to the first device path data structure.\r
   @param DevicePath2    A pointer to the second device path data structure.\r
@@ -81,7 +75,7 @@ EfiCompareDevicePath (
   private data structure.\r
 \r
   @retval EFI_SUCCESS           They are same.\r
-  @retval EFI_UNSUPPORTED       No PCI Hot Plug controler on the platform.\r
+  @retval EFI_UNSUPPORTED       No PCI Hot Plug controller on the platform.\r
   @retval EFI_OUT_OF_RESOURCES  No memory to constructor root hot plug private\r
                                 data structure.\r
 \r
@@ -137,7 +131,7 @@ InitializeHotPlugSupport (
 \r
   @param HpbDevicePath  A pointer to device path data structure to be tested.\r
   @param HpIndex        If HpIndex is not NULL, return the index of root hot\r
-                        plug in global array when TRUE is retuned.\r
+                        plug in global array when TRUE is returned.\r
 \r
   @retval TRUE          The device path is for root pci hot plug bus.\r
   @retval FALSE         The device path is not for root pci hot plug bus.\r
@@ -171,7 +165,7 @@ IsRootPciHotPlugBus (
 \r
   @param HpcDevicePath  A pointer to device path data structure to be tested.\r
   @param HpIndex        If HpIndex is not NULL, return the index of root hot\r
-                        plug in global array when TRUE is retuned.\r
+                        plug in global array when TRUE is returned.\r
 \r
   @retval TRUE          The device path is for root pci hot plug controller.\r
   @retval FALSE         The device path is not for root pci hot plug controller.\r
@@ -204,9 +198,9 @@ IsRootPciHotPlugController (
   Creating event object for PCI Hot Plug controller.\r
 \r
   @param  HpIndex   Index of hot plug device in global array.\r
-  @param  Event     The retuned event that invoke this function.\r
+  @param  Event     The returned event that invoke this function.\r
 \r
-  @return Status of create event invoken.\r
+  @return Status of create event.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -316,6 +310,94 @@ IsSHPC (
   return FALSE;\r
 }\r
 \r
+/**\r
+  Check whether PciIoDevice supports PCIe hotplug.\r
+\r
+  This is equivalent to the following condition:\r
+  - the device is either a PCIe switch downstream port or a root port,\r
+  - and the device has the SlotImplemented bit set in its PCIe capability\r
+    register,\r
+  - and the device has the HotPlugCapable bit set in its slot capabilities\r
+    register.\r
+\r
+  @param[in] PciIoDevice  The device being checked.\r
+\r
+  @retval TRUE   PciIoDevice is a PCIe port that accepts a hot-plugged device.\r
+  @retval FALSE  Otherwise.\r
+\r
+**/\r
+BOOLEAN\r
+SupportsPcieHotplug (\r
+  IN PCI_IO_DEVICE                      *PciIoDevice\r
+  )\r
+{\r
+  UINT32                       Offset;\r
+  EFI_STATUS                   Status;\r
+  PCI_REG_PCIE_CAPABILITY      Capability;\r
+  PCI_REG_PCIE_SLOT_CAPABILITY SlotCapability;\r
+\r
+  if (PciIoDevice == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Read the PCI Express Capabilities Register\r
+  //\r
+  if (!PciIoDevice->IsPciExp) {\r
+    return FALSE;\r
+  }\r
+  Offset = PciIoDevice->PciExpressCapabilityOffset +\r
+           OFFSET_OF (PCI_CAPABILITY_PCIEXP, Capability);\r
+  Status = PciIoDevice->PciIo.Pci.Read (\r
+                                    &PciIoDevice->PciIo,\r
+                                    EfiPciIoWidthUint16,\r
+                                    Offset,\r
+                                    1,\r
+                                    &Capability\r
+                                    );\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Check the contents of the register\r
+  //\r
+  switch (Capability.Bits.DevicePortType) {\r
+  case PCIE_DEVICE_PORT_TYPE_ROOT_PORT:\r
+  case PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT:\r
+    break;\r
+  default:\r
+    return FALSE;\r
+  }\r
+  if (!Capability.Bits.SlotImplemented) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Read the Slot Capabilities Register\r
+  //\r
+  Offset = PciIoDevice->PciExpressCapabilityOffset +\r
+           OFFSET_OF (PCI_CAPABILITY_PCIEXP, SlotCapability);\r
+  Status = PciIoDevice->PciIo.Pci.Read (\r
+                                    &PciIoDevice->PciIo,\r
+                                    EfiPciIoWidthUint32,\r
+                                    Offset,\r
+                                    1,\r
+                                    &SlotCapability\r
+                                    );\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Check the contents of the register\r
+  //\r
+  if (SlotCapability.Bits.HotPlugCapable) {\r
+    return TRUE;\r
+  }\r
+  return FALSE;\r
+}\r
+\r
 /**\r
   Get resource padding if the specified PCI bridge is a hot plug bus.\r
 \r
@@ -382,6 +464,14 @@ IsPciHotPlugBus (
     return TRUE;\r
   }\r
 \r
+  if (SupportsPcieHotplug (PciIoDevice)) {\r
+    //\r
+    // If the PPB is a PCIe root complex port or a switch downstream port, and\r
+    // implements a hot-plug capable slot, then also return TRUE.\r
+    //\r
+    return TRUE;\r
+  }\r
+\r
   //\r
   // Otherwise, see if it is a Root HPC\r
   //\r