1 /** @file
2   Driver Binding functions for PCI Bus module.
3 
4   Single PCI bus driver instance will manager all PCI Root Bridges in one EFI based firmware,
5   since all PCI Root Bridges' resources need to be managed together.
6   Supported() function will try to get PCI Root Bridge IO Protocol.
7   Start() function will get PCI Host Bridge Resource Allocation Protocol to manage all
8   PCI Root Bridges. So it means platform needs install PCI Root Bridge IO protocol for each
9   PCI Root Bus and install PCI Host Bridge Resource Allocation Protocol.
10 
11 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
12 SPDX-License-Identifier: BSD-2-Clause-Patent
13 
14 **/
15 
16 #include "PciBus.h"
17 
18 //
19 // PCI Bus Driver Global Variables
20 //
21 EFI_DRIVER_BINDING_PROTOCOL                   gPciBusDriverBinding = {
22   PciBusDriverBindingSupported,
23   PciBusDriverBindingStart,
24   PciBusDriverBindingStop,
25   0xa,
26   NULL,
27   NULL
28 };
29 
30 EFI_HANDLE                                    gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM];
31 EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL  *gIncompatiblePciDeviceSupport = NULL;
32 UINTN                                         gPciHostBridgeNumber = 0;
33 BOOLEAN                                       gFullEnumeration     = TRUE;
34 UINT64                                        gAllOne              = 0xFFFFFFFFFFFFFFFFULL;
35 UINT64                                        gAllZero             = 0;
36 
37 EFI_PCI_PLATFORM_PROTOCOL                     *gPciPlatformProtocol;
38 EFI_PCI_OVERRIDE_PROTOCOL                     *gPciOverrideProtocol;
39 EDKII_IOMMU_PROTOCOL                          *mIoMmuProtocol;
40 EDKII_DEVICE_SECURITY_PROTOCOL                *mDeviceSecurityProtocol;
41 
42 GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL mPciHotPlugRequest = {
43   PciHotPlugRequestNotify
44 };
45 
46 /**
47   The Entry Point for PCI Bus module. The user code starts with this function.
48 
49   Installs driver module protocols and. Creates virtual device handles for ConIn,
50   ConOut, and StdErr. Installs Simple Text In protocol, Simple Text In Ex protocol,
51   Simple Pointer protocol, Absolute Pointer protocol on those virtual handlers.
52   Installs Graphics Output protocol and/or UGA Draw protocol if needed.
53 
54   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
55   @param[in] SystemTable    A pointer to the EFI System Table.
56 
57   @retval EFI_SUCCESS       The entry point is executed successfully.
58   @retval other             Some error occurred when executing this entry point.
59 
60 **/
61 EFI_STATUS
62 EFIAPI
PciBusEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)63 PciBusEntryPoint (
64   IN EFI_HANDLE         ImageHandle,
65   IN EFI_SYSTEM_TABLE   *SystemTable
66   )
67 {
68   EFI_STATUS  Status;
69   EFI_HANDLE  Handle;
70 
71   //
72   // Initializes PCI devices pool
73   //
74   InitializePciDevicePool ();
75 
76   //
77   // Install driver model protocol(s).
78   //
79   Status = EfiLibInstallDriverBindingComponentName2 (
80              ImageHandle,
81              SystemTable,
82              &gPciBusDriverBinding,
83              ImageHandle,
84              &gPciBusComponentName,
85              &gPciBusComponentName2
86              );
87   ASSERT_EFI_ERROR (Status);
88 
89   if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
90     //
91     // If Hot Plug is supported, install EFI PCI Hot Plug Request protocol.
92     //
93     Handle = NULL;
94     Status = gBS->InstallProtocolInterface (
95                     &Handle,
96                     &gEfiPciHotPlugRequestProtocolGuid,
97                     EFI_NATIVE_INTERFACE,
98                     &mPciHotPlugRequest
99                     );
100   }
101 
102   return Status;
103 }
104 
105 /**
106   Test to see if this driver supports ControllerHandle. Any ControllerHandle
107   than contains a gEfiPciRootBridgeIoProtocolGuid protocol can be supported.
108 
109   @param  This                Protocol instance pointer.
110   @param  Controller          Handle of device to test.
111   @param  RemainingDevicePath Optional parameter use to pick a specific child
112                               device to start.
113 
114   @retval EFI_SUCCESS         This driver supports this device.
115   @retval EFI_ALREADY_STARTED This driver is already running on this device.
116   @retval other               This driver does not support this device.
117 
118 **/
119 EFI_STATUS
120 EFIAPI
PciBusDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)121 PciBusDriverBindingSupported (
122   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
123   IN EFI_HANDLE                     Controller,
124   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
125   )
126 {
127   EFI_STATUS                      Status;
128   EFI_DEVICE_PATH_PROTOCOL        *ParentDevicePath;
129   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
130   EFI_DEV_PATH_PTR                Node;
131 
132   //
133   // Check RemainingDevicePath validation
134   //
135   if (RemainingDevicePath != NULL) {
136     //
137     // Check if RemainingDevicePath is the End of Device Path Node,
138     // if yes, go on checking other conditions
139     //
140     if (!IsDevicePathEnd (RemainingDevicePath)) {
141       //
142       // If RemainingDevicePath isn't the End of Device Path Node,
143       // check its validation
144       //
145       Node.DevPath = RemainingDevicePath;
146       if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||
147           Node.DevPath->SubType != HW_PCI_DP         ||
148           DevicePathNodeLength(Node.DevPath) != sizeof(PCI_DEVICE_PATH)) {
149         return EFI_UNSUPPORTED;
150       }
151     }
152   }
153 
154   //
155   // Check if Pci Root Bridge IO protocol is installed by platform
156   //
157   Status = gBS->OpenProtocol (
158                   Controller,
159                   &gEfiPciRootBridgeIoProtocolGuid,
160                   (VOID **) &PciRootBridgeIo,
161                   This->DriverBindingHandle,
162                   Controller,
163                   EFI_OPEN_PROTOCOL_BY_DRIVER
164                   );
165   if (Status == EFI_ALREADY_STARTED) {
166     return EFI_SUCCESS;
167   }
168 
169   if (EFI_ERROR (Status)) {
170     return Status;
171   }
172 
173   //
174   // Close the I/O Abstraction(s) used to perform the supported test
175   //
176   gBS->CloseProtocol (
177         Controller,
178         &gEfiPciRootBridgeIoProtocolGuid,
179         This->DriverBindingHandle,
180         Controller
181         );
182 
183   //
184   // Open the EFI Device Path protocol needed to perform the supported test
185   //
186   Status = gBS->OpenProtocol (
187                   Controller,
188                   &gEfiDevicePathProtocolGuid,
189                   (VOID **) &ParentDevicePath,
190                   This->DriverBindingHandle,
191                   Controller,
192                   EFI_OPEN_PROTOCOL_BY_DRIVER
193                   );
194   if (Status == EFI_ALREADY_STARTED) {
195     return EFI_SUCCESS;
196   }
197 
198   if (EFI_ERROR (Status)) {
199     return Status;
200   }
201 
202   //
203   // Close protocol, don't use device path protocol in the Support() function
204   //
205   gBS->CloseProtocol (
206         Controller,
207         &gEfiDevicePathProtocolGuid,
208         This->DriverBindingHandle,
209         Controller
210         );
211 
212   return EFI_SUCCESS;
213 }
214 
215 /**
216   Start this driver on ControllerHandle and enumerate Pci bus and start
217   all device under PCI bus.
218 
219   @param  This                 Protocol instance pointer.
220   @param  Controller           Handle of device to bind driver to.
221   @param  RemainingDevicePath  Optional parameter use to pick a specific child
222                                device to start.
223 
224   @retval EFI_SUCCESS          This driver is added to ControllerHandle.
225   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.
226   @retval other                This driver does not support this device.
227 
228 **/
229 EFI_STATUS
230 EFIAPI
PciBusDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)231 PciBusDriverBindingStart (
232   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
233   IN EFI_HANDLE                   Controller,
234   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
235   )
236 {
237   EFI_STATUS                      Status;
238   EFI_DEVICE_PATH_PROTOCOL        *ParentDevicePath;
239   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
240 
241   //
242   // Initialize PciRootBridgeIo to suppress incorrect compiler warning.
243   //
244   PciRootBridgeIo = NULL;
245 
246   //
247   // Check RemainingDevicePath validation
248   //
249   if (RemainingDevicePath != NULL) {
250     //
251     // Check if RemainingDevicePath is the End of Device Path Node,
252     // if yes, return EFI_SUCCESS
253     //
254     if (IsDevicePathEnd (RemainingDevicePath)) {
255       return EFI_SUCCESS;
256     }
257   }
258 
259   gBS->LocateProtocol (
260          &gEfiIncompatiblePciDeviceSupportProtocolGuid,
261          NULL,
262          (VOID **) &gIncompatiblePciDeviceSupport
263          );
264 
265   //
266   // If PCI Platform protocol is available, get it now.
267   // If the platform implements this, it must be installed before BDS phase
268   //
269   gPciPlatformProtocol = NULL;
270   gBS->LocateProtocol (
271         &gEfiPciPlatformProtocolGuid,
272         NULL,
273         (VOID **) &gPciPlatformProtocol
274         );
275 
276   //
277   // If PCI Platform protocol doesn't exist, try to Pci Override Protocol.
278   //
279   if (gPciPlatformProtocol == NULL) {
280     gPciOverrideProtocol = NULL;
281     gBS->LocateProtocol (
282           &gEfiPciOverrideProtocolGuid,
283           NULL,
284           (VOID **) &gPciOverrideProtocol
285           );
286   }
287 
288   if (mIoMmuProtocol == NULL) {
289     gBS->LocateProtocol (
290           &gEdkiiIoMmuProtocolGuid,
291           NULL,
292           (VOID **) &mIoMmuProtocol
293           );
294   }
295 
296   if (mDeviceSecurityProtocol == NULL) {
297     gBS->LocateProtocol (
298           &gEdkiiDeviceSecurityProtocolGuid,
299           NULL,
300           (VOID **) &mDeviceSecurityProtocol
301           );
302   }
303 
304   if (PcdGetBool (PcdPciDisableBusEnumeration)) {
305     gFullEnumeration = FALSE;
306   } else {
307     gFullEnumeration = (BOOLEAN) ((SearchHostBridgeHandle (Controller) ? FALSE : TRUE));
308   }
309 
310   //
311   // Open Device Path Protocol for PCI root bridge
312   //
313   Status = gBS->OpenProtocol (
314                   Controller,
315                   &gEfiDevicePathProtocolGuid,
316                   (VOID **) &ParentDevicePath,
317                   This->DriverBindingHandle,
318                   Controller,
319                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
320                   );
321   ASSERT_EFI_ERROR (Status);
322 
323   //
324   // Report Status Code to indicate PCI bus starts
325   //
326   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
327     EFI_PROGRESS_CODE,
328     (EFI_IO_BUS_PCI | EFI_IOB_PC_INIT),
329     ParentDevicePath
330     );
331 
332   Status = EFI_SUCCESS;
333   //
334   // Enumerate the entire host bridge
335   // After enumeration, a database that records all the device information will be created
336   //
337   //
338   if (gFullEnumeration) {
339     //
340     // Get the rootbridge Io protocol to find the host bridge handle
341     //
342     Status = gBS->OpenProtocol (
343                     Controller,
344                     &gEfiPciRootBridgeIoProtocolGuid,
345                     (VOID **) &PciRootBridgeIo,
346                     gPciBusDriverBinding.DriverBindingHandle,
347                     Controller,
348                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
349                     );
350 
351     if (!EFI_ERROR (Status)) {
352       Status = PciEnumerator (Controller, PciRootBridgeIo->ParentHandle);
353     }
354   } else {
355     //
356     // If PCI bus has already done the full enumeration, never do it again
357     //
358     Status = PciEnumeratorLight (Controller);
359   }
360 
361   if (EFI_ERROR (Status)) {
362     return Status;
363   }
364 
365   //
366   // Start all the devices under the entire host bridge.
367   //
368   StartPciDevices (Controller);
369 
370   if (gFullEnumeration) {
371     gFullEnumeration = FALSE;
372 
373     Status = gBS->InstallProtocolInterface (
374                     &PciRootBridgeIo->ParentHandle,
375                     &gEfiPciEnumerationCompleteProtocolGuid,
376                     EFI_NATIVE_INTERFACE,
377                     NULL
378                     );
379     ASSERT_EFI_ERROR (Status);
380   }
381 
382   return Status;
383 }
384 
385 /**
386   Stop this driver on ControllerHandle. Support stopping any child handles
387   created by this driver.
388 
389   @param  This              Protocol instance pointer.
390   @param  Controller        Handle of device to stop driver on.
391   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
392                             children is zero stop the entire bus driver.
393   @param  ChildHandleBuffer List of Child Handles to Stop.
394 
395   @retval EFI_SUCCESS       This driver is removed ControllerHandle.
396   @retval other             This driver was not removed from this device.
397 
398 **/
399 EFI_STATUS
400 EFIAPI
PciBusDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)401 PciBusDriverBindingStop (
402   IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
403   IN  EFI_HANDLE                    Controller,
404   IN  UINTN                         NumberOfChildren,
405   IN  EFI_HANDLE                    *ChildHandleBuffer
406   )
407 {
408   EFI_STATUS  Status;
409   UINTN       Index;
410   BOOLEAN     AllChildrenStopped;
411 
412   if (NumberOfChildren == 0) {
413     //
414     // Close the bus driver
415     //
416     gBS->CloseProtocol (
417           Controller,
418           &gEfiDevicePathProtocolGuid,
419           This->DriverBindingHandle,
420           Controller
421           );
422     gBS->CloseProtocol (
423           Controller,
424           &gEfiPciRootBridgeIoProtocolGuid,
425           This->DriverBindingHandle,
426           Controller
427           );
428 
429     DestroyRootBridgeByHandle (
430       Controller
431       );
432 
433     return EFI_SUCCESS;
434   }
435 
436   //
437   // Stop all the children
438   //
439 
440   AllChildrenStopped = TRUE;
441 
442   for (Index = 0; Index < NumberOfChildren; Index++) {
443 
444     //
445     // De register all the pci device
446     //
447     Status = DeRegisterPciDevice (Controller, ChildHandleBuffer[Index]);
448 
449     if (EFI_ERROR (Status)) {
450       AllChildrenStopped = FALSE;
451     }
452   }
453 
454   if (!AllChildrenStopped) {
455     return EFI_DEVICE_ERROR;
456   }
457 
458   return EFI_SUCCESS;
459 }
460 
461