]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
MdeModulePkg/Pci: Add DeviceSecurity support.
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciEnumerator.c
index bd256cfc8564e334bc338419a6429d59a03397b4..8db1ebf8ec4112a5ea3765e78b033c5f1e97a8c7 100644 (file)
@@ -1,14 +1,9 @@
 /** @file\r
   PCI eunmeration implementation on entire PCI bus system for PCI Bus module.\r
 \r
-Copyright (c) 2006 - 2009, Intel Corporation\r
-All rights reserved. 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
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -18,7 +13,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
   This routine is used to enumerate entire pci bus system\r
   in a given platform.\r
 \r
-  @param Controller  Parent controller handle.\r
+  @param Controller          Parent controller handle.\r
+  @param HostBridgeHandle    Host bridge handle.\r
 \r
   @retval EFI_SUCCESS    PCI enumeration finished successfully.\r
   @retval other          Some error occurred when enumerating the pci bus system.\r
@@ -26,42 +22,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/\r
 EFI_STATUS\r
 PciEnumerator (\r
-  IN EFI_HANDLE                    Controller\r
+  IN EFI_HANDLE                    Controller,\r
+  IN EFI_HANDLE                    HostBridgeHandle\r
   )\r
 {\r
-  EFI_HANDLE                                        Handle;\r
-  EFI_HANDLE                                        HostBridgeHandle;\r
   EFI_STATUS                                        Status;\r
   EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc;\r
-  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL                   *PciRootBridgeIo;\r
-\r
-  //\r
-  // If PCI bus has already done the full enumeration, never do it again\r
-  //\r
-  if (!gFullEnumeration) {\r
-    return PciEnumeratorLight (Controller);\r
-  }\r
-\r
-  //\r
-  // Get the rootbridge Io protocol to find the host bridge handle\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiPciRootBridgeIoProtocolGuid,\r
-                  (VOID **) &PciRootBridgeIo,\r
-                  gPciBusDriverBinding.DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Get the host bridge handle\r
-  //\r
-  HostBridgeHandle = PciRootBridgeIo->ParentHandle;\r
 \r
   //\r
   // Get the pci host bridge resource allocation protocol\r
@@ -82,7 +48,11 @@ PciEnumerator (
   //\r
   // Notify the pci bus enumeration is about to begin\r
   //\r
-  NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration);\r
+  Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
   //\r
   // Start the bus allocation phase\r
@@ -105,7 +75,11 @@ PciEnumerator (
   //\r
   // Notify the pci bus enumeration is about to complete\r
   //\r
-  NotifyPhase (PciResAlloc, EfiPciHostBridgeEndEnumeration);\r
+  Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeEndEnumeration);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
   //\r
   // Process P2C\r
@@ -124,19 +98,6 @@ PciEnumerator (
     return Status;\r
   }\r
 \r
-  gFullEnumeration = FALSE;\r
-\r
-  Handle = NULL;\r
-  Status = gBS->InstallProtocolInterface (\r
-                  &Handle,\r
-                  &gEfiPciEnumerationCompleteProtocolGuid,\r
-                  EFI_NATIVE_INTERFACE,\r
-                  NULL\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -158,10 +119,16 @@ PciRootBridgeEnumerator (
 {\r
   EFI_STATUS                        Status;\r
   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration1;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration2;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration3;\r
   UINT8                             SubBusNumber;\r
   UINT8                             StartBusNumber;\r
   UINT8                             PaddedBusRange;\r
   EFI_HANDLE                        RootBridgeHandle;\r
+  UINT8                             Desc;\r
+  UINT64                            AddrLen;\r
+  UINT64                            AddrRangeMin;\r
 \r
   SubBusNumber    = 0;\r
   StartBusNumber  = 0;\r
@@ -174,7 +141,7 @@ PciRootBridgeEnumerator (
 \r
   REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
     EFI_PROGRESS_CODE,\r
-    EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_BUS_ENUM,\r
+    EFI_IO_BUS_PCI | EFI_IOB_PCI_BUS_ENUM,\r
     RootBridgeDev->DevicePath\r
     );\r
 \r
@@ -191,11 +158,40 @@ PciRootBridgeEnumerator (
     return Status;\r
   }\r
 \r
+  if (Configuration == NULL || Configuration->Desc == ACPI_END_TAG_DESCRIPTOR) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  RootBridgeDev->BusNumberRanges = Configuration;\r
+\r
+  //\r
+  // Sort the descriptors in ascending order\r
+  //\r
+  for (Configuration1 = Configuration; Configuration1->Desc != ACPI_END_TAG_DESCRIPTOR; Configuration1++) {\r
+    Configuration2 = Configuration1;\r
+    for (Configuration3 = Configuration1 + 1; Configuration3->Desc != ACPI_END_TAG_DESCRIPTOR; Configuration3++) {\r
+      if (Configuration2->AddrRangeMin > Configuration3->AddrRangeMin) {\r
+        Configuration2 = Configuration3;\r
+      }\r
+    }\r
+    //\r
+    // All other fields other than AddrRangeMin and AddrLen are ignored in a descriptor,\r
+    // so only need to swap these two fields.\r
+    //\r
+    if (Configuration2 != Configuration1) {\r
+      AddrRangeMin = Configuration1->AddrRangeMin;\r
+      Configuration1->AddrRangeMin = Configuration2->AddrRangeMin;\r
+      Configuration2->AddrRangeMin = AddrRangeMin;\r
+\r
+      AddrLen = Configuration1->AddrLen;\r
+      Configuration1->AddrLen = Configuration2->AddrLen;\r
+      Configuration2->AddrLen = AddrLen;\r
+    }\r
+  }\r
+\r
   //\r
   // Get the bus number to start with\r
   //\r
   StartBusNumber = (UINT8) (Configuration->AddrRangeMin);\r
-  PaddedBusRange  = (UINT8) (Configuration->AddrRangeMax);\r
 \r
   //\r
   // Initialize the subordinate bus number\r
@@ -215,7 +211,7 @@ PciRootBridgeEnumerator (
   //\r
   Status = PciScanBus (\r
             RootBridgeDev,\r
-            (UINT8) (Configuration->AddrRangeMin),\r
+            StartBusNumber,\r
             &SubBusNumber,\r
             &PaddedBusRange\r
             );\r
@@ -228,7 +224,28 @@ PciRootBridgeEnumerator (
   //\r
   // Assign max bus number scanned\r
   //\r
-  Configuration->AddrLen = SubBusNumber - StartBusNumber + 1 + PaddedBusRange;\r
+\r
+  Status = PciAllocateBusNumber (RootBridgeDev, SubBusNumber, PaddedBusRange, &SubBusNumber);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Find the bus range which contains the higest bus number, then returns the number of buses\r
+  // that should be decoded.\r
+  //\r
+  while (Configuration->AddrRangeMin + Configuration->AddrLen - 1 < SubBusNumber) {\r
+    Configuration++;\r
+  }\r
+  AddrLen = Configuration->AddrLen;\r
+  Configuration->AddrLen = SubBusNumber - Configuration->AddrRangeMin + 1;\r
+\r
+  //\r
+  // Save the Desc field of the next descriptor. Mark the next descriptor as an END descriptor.\r
+  //\r
+  Configuration++;\r
+  Desc = Configuration->Desc;\r
+  Configuration->Desc = ACPI_END_TAG_DESCRIPTOR;\r
 \r
   //\r
   // Set bus number\r
@@ -236,16 +253,16 @@ PciRootBridgeEnumerator (
   Status = PciResAlloc->SetBusNumbers (\r
                           PciResAlloc,\r
                           RootBridgeHandle,\r
-                          Configuration\r
+                          RootBridgeDev->BusNumberRanges\r
                           );\r
 \r
-  FreePool (Configuration);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
+  //\r
+  // Restore changed fields\r
+  //\r
+  Configuration->Desc = Desc;\r
+  (Configuration - 1)->AddrLen = AddrLen;\r
 \r
-  return EFI_SUCCESS;\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -345,13 +362,24 @@ PciAssignBusNumber (
                 Func\r
                 );\r
 \r
+      if (EFI_ERROR (Status) && Func == 0) {\r
+        //\r
+        // go to next device if there is no Function 0\r
+        //\r
+        break;\r
+      }\r
+\r
       if (!EFI_ERROR (Status)   &&\r
           (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {\r
 \r
         //\r
         // Reserved one bus for cardbus bridge\r
         //\r
-        SecondBus = ++(*SubBusNumber);\r
+        Status = PciAllocateBusNumber (Bridge, *SubBusNumber, 1, SubBusNumber);\r
+        if (EFI_ERROR (Status)) {\r
+          return Status;\r
+        }\r
+        SecondBus = *SubBusNumber;\r
 \r
         Register  = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
 \r
@@ -475,6 +503,7 @@ DetermineRootBridgeAttributes (
   }\r
 \r
   if ((Attributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) != 0) {\r
+    RootBridgeDev->Decodes |= EFI_BRIDGE_MEM64_DECODE_SUPPORTED;\r
     RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;\r
   }\r
 \r
@@ -493,15 +522,15 @@ DetermineRootBridgeAttributes (
   @return Max size of option rom needed.\r
 \r
 **/\r
-UINT64\r
+UINT32\r
 GetMaxOptionRomSize (\r
   IN PCI_IO_DEVICE   *Bridge\r
   )\r
 {\r
   LIST_ENTRY      *CurrentLink;\r
   PCI_IO_DEVICE   *Temp;\r
-  UINT64          MaxOptionRomSize;\r
-  UINT64          TempOptionRomSize;\r
+  UINT32          MaxOptionRomSize;\r
+  UINT32          TempOptionRomSize;\r
 \r
   MaxOptionRomSize = 0;\r
 \r
@@ -733,7 +762,6 @@ RejectPciDevice (
     if (Temp == PciDevice) {\r
       InitializePciDevice (Temp);\r
       RemoveEntryList (CurrentLink);\r
-      FreePciDevice (Temp);\r
       return EFI_SUCCESS;\r
     }\r
 \r
@@ -888,7 +916,7 @@ GetMaxResourceConsumerDevice (
   @param Mem64ResStatus   Status of 64-bit memory resource node.\r
   @param PMem64ResStatus  Status of 64-bit Prefetchable memory resource node.\r
 \r
-  @retval EFI_SUCCESS     Successfully adjusted resoruce on host bridge.\r
+  @retval EFI_SUCCESS     Successfully adjusted resource on host bridge.\r
   @retval EFI_ABORTED     Host bridge hasn't this resource type or no resource be adjusted.\r
 \r
 **/\r
@@ -974,6 +1002,11 @@ PciHostBridgeAdjustAllocation (
     //\r
     Status = RejectPciDevice (PciResNode->PciDev);\r
     if (Status == EFI_SUCCESS) {\r
+      DEBUG ((\r
+        EFI_D_ERROR,\r
+        "PciBus: [%02x|%02x|%02x] was rejected due to resource confliction.\n",\r
+        PciResNode->PciDev->BusNumber, PciResNode->PciDev->DeviceNumber, PciResNode->PciDev->FunctionNumber\r
+        ));\r
 \r
       //\r
       // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code\r
@@ -982,7 +1015,7 @@ PciHostBridgeAdjustAllocation (
       // Have no way to get ReqRes, AllocRes & Bar here\r
       //\r
       ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));\r
-      AllocFailExtendedData.DevicePathSize = sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
+      AllocFailExtendedData.DevicePathSize = (UINT16) sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
       AllocFailExtendedData.DevicePath     = (UINT8 *) PciResNode->PciDev->DevicePath;\r
       AllocFailExtendedData.Bar            = PciResNode->Bar;\r
 \r
@@ -1012,7 +1045,7 @@ PciHostBridgeAdjustAllocation (
 }\r
 \r
 /**\r
-  Summary requests for all resource type, and contruct ACPI resource\r
+  Summary requests for all resource type, and construct ACPI resource\r
   requestor instance.\r
 \r
   @param Bridge           detecting bridge\r
@@ -1024,7 +1057,7 @@ PciHostBridgeAdjustAllocation (
   @param Config           Output buffer holding new constructed APCI resource requestor\r
 \r
   @retval EFI_SUCCESS           Successfully constructed ACPI resource.\r
-  @retval EFI_OUT_OF_RESOURCES  No memory availabe.\r
+  @retval EFI_OUT_OF_RESOURCES  No memory available.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -1107,7 +1140,7 @@ ConstructAcpiResourceRequestor (
     //\r
     if ((Aperture & 0x01) != 0) {\r
       Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
-      Ptr->Len      = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+      Ptr->Len      = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);\r
       //\r
       // Io\r
       //\r
@@ -1126,7 +1159,7 @@ ConstructAcpiResourceRequestor (
     //\r
     if ((Aperture & 0x02) != 0) {\r
       Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
-      Ptr->Len      = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+      Ptr->Len      = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);\r
       //\r
       // Mem\r
       //\r
@@ -1150,7 +1183,7 @@ ConstructAcpiResourceRequestor (
     //\r
     if ((Aperture & 0x04) != 0) {\r
       Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
-      Ptr->Len      = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+      Ptr->Len      = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);\r
       //\r
       // Mem\r
       //\r
@@ -1173,7 +1206,7 @@ ConstructAcpiResourceRequestor (
     //\r
     if ((Aperture & 0x08) != 0) {\r
       Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
-      Ptr->Len      = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+      Ptr->Len      = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);\r
       //\r
       // Mem\r
       //\r
@@ -1196,7 +1229,7 @@ ConstructAcpiResourceRequestor (
     //\r
     if ((Aperture & 0x10) != 0) {\r
       Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
-      Ptr->Len      = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+      Ptr->Len      = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);\r
       //\r
       // Mem\r
       //\r
@@ -1228,15 +1261,12 @@ ConstructAcpiResourceRequestor (
     //\r
     // If there is no resource request\r
     //\r
-    Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
+    Configuration = AllocateZeroPool (sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
     if (Configuration == NULL) {\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
 \r
-    Ptr               = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration);\r
-    Ptr->Desc         = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
-\r
-    PtrEnd            = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Ptr + 1);\r
+    PtrEnd            = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Configuration);\r
     PtrEnd->Desc      = ACPI_END_TAG_DESCRIPTOR;\r
     PtrEnd->Checksum  = 0;\r
   }\r
@@ -1428,7 +1458,7 @@ PciBridgeResourceAllocator (
   IoBridge = CreateResourceNode (\r
                Bridge,\r
                0,\r
-               0xFFF,\r
+               Bridge->BridgeIoAlignment,\r
                0,\r
                PciBarTypeIo16,\r
                PciResUsageTypical\r
@@ -1776,7 +1806,7 @@ NotifyPhase (
                             Phase,\r
                             ChipsetEntry\r
                             );\r
-  }  \r
+  }\r
 \r
   Status = PciResAlloc->NotifyPhase (\r
                           PciResAlloc,\r
@@ -1806,7 +1836,7 @@ NotifyPhase (
                             );\r
   }\r
 \r
-  return EFI_SUCCESS;\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -2007,7 +2037,7 @@ PciHotPlugRequestNotify (
       return EFI_INVALID_PARAMETER;\r
     }\r
   }\r
-  \r
+\r
   Status = gBS->OpenProtocol (\r
                   Controller,\r
                   &gEfiPciIoProtocolGuid,\r
@@ -2034,6 +2064,14 @@ PciHotPlugRequestNotify (
   RootBridgeHandle = Temp->Handle;\r
 \r
   if (Operation == EfiPciHotPlugRequestAdd) {\r
+    //\r
+    // Report Status Code to indicate hot plug happens\r
+    //\r
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+      EFI_PROGRESS_CODE,\r
+      (EFI_IO_BUS_PCI | EFI_IOB_PC_HOTPLUG),\r
+      Temp->DevicePath\r
+      );\r
 \r
     if (NumberOfChildren != NULL) {\r
       *NumberOfChildren = 0;\r