]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
SecurityPkg: Update VariableAuthenticated driver with following changes:
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciLib.c
CommitLineData
9060e3ec 1/** @file\r
2 Internal library implementation for PCI Bus module.\r
3\r
8db6a82c 4Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 5This program and the accompanying materials\r
9060e3ec 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "PciBus.h"\r
16\r
8db6a82c
RN
17GLOBAL_REMOVE_IF_UNREFERENCED\r
18CHAR16 *mBarTypeStr[] = {\r
19 L"Unknow",\r
20 L" Io16",\r
21 L" Io32",\r
22 L" Mem32",\r
23 L"PMem32",\r
24 L" Mem64",\r
25 L"PMem64",\r
26 L" Io",\r
27 L" Mem",\r
28 L"Unknow"\r
29 };\r
9060e3ec 30\r
31/**\r
32 Retrieve the PCI Card device BAR information via PciIo interface.\r
33\r
34 @param PciIoDevice PCI Card device instance.\r
35\r
36**/\r
37VOID\r
38GetBackPcCardBar (\r
39 IN PCI_IO_DEVICE *PciIoDevice\r
40 )\r
41{\r
42 UINT32 Address;\r
43\r
44 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
45 return;\r
46 }\r
47\r
48 //\r
49 // Read PciBar information from the bar register\r
50 //\r
51 if (!gFullEnumeration) {\r
52 Address = 0;\r
53 PciIoDevice->PciIo.Pci.Read (\r
54 &(PciIoDevice->PciIo),\r
55 EfiPciIoWidthUint32,\r
56 PCI_CARD_MEMORY_BASE_0,\r
57 1,\r
58 &Address\r
59 );\r
60\r
61 (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress = (UINT64) (Address);\r
62 (PciIoDevice->PciBar)[P2C_MEM_1].Length = 0x2000000;\r
63 (PciIoDevice->PciBar)[P2C_MEM_1].BarType = PciBarTypeMem32;\r
64\r
65 Address = 0;\r
66 PciIoDevice->PciIo.Pci.Read (\r
67 &(PciIoDevice->PciIo),\r
68 EfiPciIoWidthUint32,\r
69 PCI_CARD_MEMORY_BASE_1,\r
70 1,\r
71 &Address\r
72 );\r
73 (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress = (UINT64) (Address);\r
74 (PciIoDevice->PciBar)[P2C_MEM_2].Length = 0x2000000;\r
75 (PciIoDevice->PciBar)[P2C_MEM_2].BarType = PciBarTypePMem32;\r
76\r
77 Address = 0;\r
78 PciIoDevice->PciIo.Pci.Read (\r
79 &(PciIoDevice->PciIo),\r
80 EfiPciIoWidthUint32,\r
81 PCI_CARD_IO_BASE_0_LOWER,\r
82 1,\r
83 &Address\r
84 );\r
85 (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress = (UINT64) (Address);\r
86 (PciIoDevice->PciBar)[P2C_IO_1].Length = 0x100;\r
87 (PciIoDevice->PciBar)[P2C_IO_1].BarType = PciBarTypeIo16;\r
88\r
89 Address = 0;\r
90 PciIoDevice->PciIo.Pci.Read (\r
91 &(PciIoDevice->PciIo),\r
92 EfiPciIoWidthUint32,\r
93 PCI_CARD_IO_BASE_1_LOWER,\r
94 1,\r
95 &Address\r
96 );\r
97 (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress = (UINT64) (Address);\r
98 (PciIoDevice->PciBar)[P2C_IO_2].Length = 0x100;\r
99 (PciIoDevice->PciBar)[P2C_IO_2].BarType = PciBarTypeIo16;\r
100\r
101 }\r
102\r
103 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
104 GetResourcePaddingForHpb (PciIoDevice);\r
105 }\r
106}\r
107\r
108/**\r
109 Remove rejected pci device from specific root bridge\r
110 handle.\r
111\r
112 @param RootBridgeHandle Specific parent root bridge handle.\r
113 @param Bridge Bridge device instance.\r
114\r
115**/\r
116VOID\r
117RemoveRejectedPciDevices (\r
118 IN EFI_HANDLE RootBridgeHandle,\r
119 IN PCI_IO_DEVICE *Bridge\r
120 )\r
121{\r
122 PCI_IO_DEVICE *Temp;\r
123 LIST_ENTRY *CurrentLink;\r
124 LIST_ENTRY *LastLink;\r
125\r
126 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
127 return;\r
128 }\r
129\r
130 CurrentLink = Bridge->ChildList.ForwardLink;\r
131\r
132 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
133\r
134 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
135\r
136 if (IS_PCI_BRIDGE (&Temp->Pci)) {\r
137 //\r
138 // Remove rejected devices recusively\r
139 //\r
140 RemoveRejectedPciDevices (RootBridgeHandle, Temp);\r
141 } else {\r
142 //\r
143 // Skip rejection for all PPBs, while detect rejection for others\r
144 //\r
145 if (IsPciDeviceRejected (Temp)) {\r
146\r
147 //\r
148 // For P2C, remove all devices on it\r
149 //\r
150 if (!IsListEmpty (&Temp->ChildList)) {\r
151 RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);\r
152 }\r
153\r
154 //\r
155 // Finally remove itself\r
156 //\r
157 LastLink = CurrentLink->BackLink;\r
158 RemoveEntryList (CurrentLink);\r
159 FreePciDevice (Temp);\r
160\r
161 CurrentLink = LastLink;\r
162 }\r
163 }\r
164\r
165 CurrentLink = CurrentLink->ForwardLink;\r
166 }\r
167}\r
168\r
8db6a82c
RN
169/**\r
170 Dump the resourc map of the bridge device.\r
171\r
172 @param[in] BridgeResource Resource descriptor of the bridge device.\r
173**/\r
174VOID\r
175DumpBridgeResource (\r
176 IN PCI_RESOURCE_NODE *BridgeResource\r
177 )\r
178{\r
179 LIST_ENTRY *Link;\r
180 PCI_RESOURCE_NODE *Resource;\r
181 PCI_BAR *Bar;\r
182\r
183 if ((BridgeResource != NULL) && (BridgeResource->Length != 0)) {\r
184 DEBUG ((\r
185 EFI_D_INFO, "Type = %s; Base = 0x%x;\tLength = 0x%x;\tAlignment = 0x%x\n",\r
186 mBarTypeStr[MIN (BridgeResource->ResType, PciBarTypeMaxType)],\r
187 BridgeResource->PciDev->PciBar[BridgeResource->Bar].BaseAddress,\r
188 BridgeResource->Length, BridgeResource->Alignment\r
189 ));\r
190 for ( Link = BridgeResource->ChildList.ForwardLink\r
191 ; Link != &BridgeResource->ChildList\r
192 ; Link = Link->ForwardLink\r
193 ) {\r
194 Resource = RESOURCE_NODE_FROM_LINK (Link);\r
195 if (Resource->ResourceUsage == PciResUsageTypical) {\r
196 Bar = Resource->Virtual ? Resource->PciDev->VfPciBar : Resource->PciDev->PciBar;\r
197 DEBUG ((\r
198 EFI_D_INFO, " Base = 0x%x;\tLength = 0x%x;\tAlignment = 0x%x;\tOwner = %s ",\r
199 Bar[Resource->Bar].BaseAddress, Resource->Length, Resource->Alignment,\r
200 IS_PCI_BRIDGE (&Resource->PciDev->Pci) ? L"PPB" :\r
201 IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci) ? L"P2C" :\r
202 L"PCI"\r
203 ));\r
204\r
205 if ((!IS_PCI_BRIDGE (&Resource->PciDev->Pci) && !IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci)) ||\r
206 (IS_PCI_BRIDGE (&Resource->PciDev->Pci) && (Resource->Bar < PPB_IO_RANGE)) ||\r
207 (IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci) && (Resource->Bar < P2C_MEM_1))\r
208 ) {\r
209 //\r
210 // The resource requirement comes from the device itself.\r
211 //\r
212 DEBUG ((\r
213 EFI_D_INFO, " [%02x|%02x|%02x:%02x]\n",\r
214 Resource->PciDev->BusNumber, Resource->PciDev->DeviceNumber,\r
215 Resource->PciDev->FunctionNumber, Bar[Resource->Bar].Offset\r
216 ));\r
217 } else {\r
218 //\r
219 // The resource requirement comes from the subordinate devices.\r
220 //\r
221 DEBUG ((\r
222 EFI_D_INFO, " [%02x|%02x|%02x:**]\n",\r
223 Resource->PciDev->BusNumber, Resource->PciDev->DeviceNumber,\r
224 Resource->PciDev->FunctionNumber\r
225 ));\r
226 }\r
227 } else {\r
228 DEBUG ((EFI_D_INFO, " Padding:Length = 0x%x;\tAlignment = 0x%x\n", Resource->Length, Resource->Alignment));\r
229 }\r
230 }\r
231 }\r
232}\r
233\r
234/**\r
235 Find the corresponding resource node for the Device in child list of BridgeResource.\r
236 \r
237 @param[in] Device Pointer to PCI_IO_DEVICE.\r
238 @param[in] BridgeResource Pointer to PCI_RESOURCE_NODE.\r
239 \r
240 @return !NULL The corresponding resource node for the Device.\r
241 @return NULL No corresponding resource node for the Device.\r
242**/\r
243PCI_RESOURCE_NODE *\r
244FindResourceNode (\r
245 IN PCI_IO_DEVICE *Device,\r
246 IN PCI_RESOURCE_NODE *BridgeResource\r
247 )\r
248{\r
249 LIST_ENTRY *Link;\r
250 PCI_RESOURCE_NODE *Resource;\r
251\r
252 for ( Link = BridgeResource->ChildList.ForwardLink\r
253 ; Link != &BridgeResource->ChildList\r
254 ; Link = Link->ForwardLink\r
255 ) {\r
256 Resource = RESOURCE_NODE_FROM_LINK (Link);\r
257 if (Resource->PciDev == Device) {\r
258 return Resource;\r
259 }\r
260 }\r
261\r
262 return NULL;\r
263}\r
264\r
265/**\r
266 Dump the resource map of all the devices under Bridge.\r
267 \r
268 @param[in] Bridge Bridge device instance.\r
269 @param[in] IoNode IO resource descriptor for the bridge device.\r
270 @param[in] Mem32Node Mem32 resource descriptor for the bridge device.\r
271 @param[in] PMem32Node PMem32 resource descriptor for the bridge device.\r
272 @param[in] Mem64Node Mem64 resource descriptor for the bridge device.\r
273 @param[in] PMem64Node PMem64 resource descriptor for the bridge device.\r
274**/\r
275VOID\r
276DumpResourceMap (\r
277 IN PCI_IO_DEVICE *Bridge,\r
278 IN PCI_RESOURCE_NODE *IoNode,\r
279 IN PCI_RESOURCE_NODE *Mem32Node,\r
280 IN PCI_RESOURCE_NODE *PMem32Node,\r
281 IN PCI_RESOURCE_NODE *Mem64Node,\r
282 IN PCI_RESOURCE_NODE *PMem64Node\r
283 )\r
284{\r
285 EFI_STATUS Status;\r
286 LIST_ENTRY *Link;\r
287 PCI_IO_DEVICE *Device;\r
288 PCI_RESOURCE_NODE *ChildIoNode;\r
289 PCI_RESOURCE_NODE *ChildMem32Node;\r
290 PCI_RESOURCE_NODE *ChildPMem32Node;\r
291 PCI_RESOURCE_NODE *ChildMem64Node;\r
292 PCI_RESOURCE_NODE *ChildPMem64Node;\r
293 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *ToText;\r
294 CHAR16 *Str;\r
295\r
296 DEBUG ((EFI_D_INFO, "PciBus: Resource Map for "));\r
297\r
298 Status = gBS->OpenProtocol (\r
299 Bridge->Handle,\r
300 &gEfiPciRootBridgeIoProtocolGuid,\r
301 NULL,\r
302 NULL,\r
303 NULL,\r
304 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
305 );\r
306 if (EFI_ERROR (Status)) {\r
307 DEBUG ((\r
308 EFI_D_INFO, "Bridge [%02x|%02x|%02x]\n",\r
309 Bridge->BusNumber, Bridge->DeviceNumber, Bridge->FunctionNumber\r
310 ));\r
311 } else {\r
312 Status = gBS->LocateProtocol (\r
313 &gEfiDevicePathToTextProtocolGuid,\r
314 NULL,\r
315 (VOID **) &ToText\r
316 );\r
317 Str = NULL;\r
318 if (!EFI_ERROR (Status)) {\r
319 Str = ToText->ConvertDevicePathToText (\r
320 DevicePathFromHandle (Bridge->Handle),\r
321 FALSE,\r
322 FALSE\r
323 );\r
324 }\r
325 DEBUG ((EFI_D_INFO, "Root Bridge %s\n", Str != NULL ? Str : L""));\r
326 if (Str != NULL) {\r
327 FreePool (Str);\r
328 }\r
329 }\r
330\r
331 DumpBridgeResource (IoNode);\r
332 DumpBridgeResource (Mem32Node);\r
333 DumpBridgeResource (PMem32Node);\r
334 DumpBridgeResource (Mem64Node);\r
335 DumpBridgeResource (PMem64Node);\r
336 DEBUG ((EFI_D_INFO, "\n"));\r
337\r
338 for ( Link = Bridge->ChildList.ForwardLink\r
339 ; Link != &Bridge->ChildList\r
340 ; Link = Link->ForwardLink\r
341 ) {\r
342 Device = PCI_IO_DEVICE_FROM_LINK (Link);\r
343 if (IS_PCI_BRIDGE (&Device->Pci)) {\r
344\r
345 ChildIoNode = (IoNode == NULL ? NULL : FindResourceNode (Device, IoNode));\r
346 ChildMem32Node = (Mem32Node == NULL ? NULL : FindResourceNode (Device, Mem32Node));\r
347 ChildPMem32Node = (PMem32Node == NULL ? NULL : FindResourceNode (Device, PMem32Node));\r
348 ChildMem64Node = (Mem64Node == NULL ? NULL : FindResourceNode (Device, Mem64Node));\r
349 ChildPMem64Node = (PMem64Node == NULL ? NULL : FindResourceNode (Device, PMem64Node));\r
350\r
351 DumpResourceMap (\r
352 Device,\r
353 ChildIoNode,\r
354 ChildMem32Node,\r
355 ChildPMem32Node,\r
356 ChildMem64Node,\r
357 ChildPMem64Node\r
358 );\r
359 }\r
360 }\r
361}\r
362\r
9060e3ec 363/**\r
364 Submits the I/O and memory resource requirements for the specified PCI Host Bridge.\r
365\r
366 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
367\r
368 @retval EFI_SUCCESS Successfully finished resource allocation.\r
369 @retval EFI_NOT_FOUND Cannot get root bridge instance.\r
370 @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources if no hot plug supported.\r
371 @retval other Some error occurred when allocating resources for the PCI Host Bridge.\r
372\r
373 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
374\r
375**/\r
376EFI_STATUS\r
377PciHostBridgeResourceAllocator (\r
378 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
379 )\r
380{\r
381 PCI_IO_DEVICE *RootBridgeDev;\r
382 EFI_HANDLE RootBridgeHandle;\r
383 VOID *AcpiConfig;\r
384 EFI_STATUS Status;\r
385 UINT64 IoBase;\r
386 UINT64 Mem32Base;\r
387 UINT64 PMem32Base;\r
388 UINT64 Mem64Base;\r
389 UINT64 PMem64Base;\r
390 UINT64 IoResStatus;\r
391 UINT64 Mem32ResStatus;\r
392 UINT64 PMem32ResStatus;\r
393 UINT64 Mem64ResStatus;\r
394 UINT64 PMem64ResStatus;\r
395 UINT64 MaxOptionRomSize;\r
396 PCI_RESOURCE_NODE *IoBridge;\r
397 PCI_RESOURCE_NODE *Mem32Bridge;\r
398 PCI_RESOURCE_NODE *PMem32Bridge;\r
399 PCI_RESOURCE_NODE *Mem64Bridge;\r
400 PCI_RESOURCE_NODE *PMem64Bridge;\r
401 PCI_RESOURCE_NODE IoPool;\r
402 PCI_RESOURCE_NODE Mem32Pool;\r
403 PCI_RESOURCE_NODE PMem32Pool;\r
404 PCI_RESOURCE_NODE Mem64Pool;\r
405 PCI_RESOURCE_NODE PMem64Pool;\r
406 BOOLEAN ReAllocate;\r
407 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData;\r
408 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;\r
409\r
410 //\r
411 // Reallocate flag\r
412 //\r
413 ReAllocate = FALSE;\r
414\r
415 //\r
416 // It may try several times if the resource allocation fails\r
417 //\r
418 while (TRUE) {\r
419 //\r
420 // Initialize resource pool\r
421 //\r
422 InitializeResourcePool (&IoPool, PciBarTypeIo16);\r
423 InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);\r
424 InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);\r
425 InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);\r
426 InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);\r
427\r
428 RootBridgeDev = NULL;\r
429 RootBridgeHandle = 0;\r
430\r
431 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
432 //\r
433 // Get Root Bridge Device by handle\r
434 //\r
435 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
436\r
437 if (RootBridgeDev == NULL) {\r
438 return EFI_NOT_FOUND;\r
439 }\r
440\r
441 //\r
442 // Create the entire system resource map from the information collected by\r
443 // enumerator. Several resource tree was created\r
444 //\r
445\r
1ef26783 446 //\r
447 // If non-stardard PCI Bridge I/O window alignment is supported,\r
448 // set I/O aligment to minimum possible alignment for root bridge.\r
449 //\r
9060e3ec 450 IoBridge = CreateResourceNode (\r
451 RootBridgeDev,\r
452 0,\r
1ef26783 453 FeaturePcdGet (PcdPciBridgeIoAlignmentProbe) ? 0x1FF: 0xFFF,\r
8db6a82c 454 RB_IO_RANGE,\r
9060e3ec 455 PciBarTypeIo16,\r
456 PciResUsageTypical\r
457 );\r
458\r
459 Mem32Bridge = CreateResourceNode (\r
460 RootBridgeDev,\r
461 0,\r
462 0xFFFFF,\r
8db6a82c 463 RB_MEM32_RANGE,\r
9060e3ec 464 PciBarTypeMem32,\r
465 PciResUsageTypical\r
466 );\r
467\r
468 PMem32Bridge = CreateResourceNode (\r
469 RootBridgeDev,\r
470 0,\r
471 0xFFFFF,\r
8db6a82c 472 RB_PMEM32_RANGE,\r
9060e3ec 473 PciBarTypePMem32,\r
474 PciResUsageTypical\r
475 );\r
476\r
477 Mem64Bridge = CreateResourceNode (\r
478 RootBridgeDev,\r
479 0,\r
480 0xFFFFF,\r
8db6a82c 481 RB_MEM64_RANGE,\r
9060e3ec 482 PciBarTypeMem64,\r
483 PciResUsageTypical\r
484 );\r
485\r
486 PMem64Bridge = CreateResourceNode (\r
487 RootBridgeDev,\r
488 0,\r
489 0xFFFFF,\r
8db6a82c 490 RB_PMEM64_RANGE,\r
9060e3ec 491 PciBarTypePMem64,\r
492 PciResUsageTypical\r
493 );\r
494\r
495 //\r
496 // Create resourcemap by going through all the devices subject to this root bridge\r
497 //\r
498 CreateResourceMap (\r
499 RootBridgeDev,\r
500 IoBridge,\r
501 Mem32Bridge,\r
502 PMem32Bridge,\r
503 Mem64Bridge,\r
504 PMem64Bridge\r
505 );\r
506\r
507 //\r
508 // Get the max ROM size that the root bridge can process\r
509 //\r
510 RootBridgeDev->RomSize = Mem32Bridge->Length;\r
511\r
512 //\r
513 // Skip to enlarge the resource request during realloction\r
514 //\r
515 if (!ReAllocate) {\r
516 //\r
517 // Get Max Option Rom size for current root bridge\r
518 //\r
519 MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);\r
520\r
521 //\r
522 // Enlarger the mem32 resource to accomdate the option rom\r
523 // if the mem32 resource is not enough to hold the rom\r
524 //\r
525 if (MaxOptionRomSize > Mem32Bridge->Length) {\r
526\r
527 Mem32Bridge->Length = MaxOptionRomSize;\r
528 RootBridgeDev->RomSize = MaxOptionRomSize;\r
529\r
530 //\r
531 // Alignment should be adjusted as well\r
532 //\r
533 if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {\r
534 Mem32Bridge->Alignment = MaxOptionRomSize - 1;\r
535 }\r
536 }\r
537 }\r
538\r
539 //\r
540 // Based on the all the resource tree, contruct ACPI resource node to\r
541 // submit the resource aperture to pci host bridge protocol\r
542 //\r
543 Status = ConstructAcpiResourceRequestor (\r
544 RootBridgeDev,\r
545 IoBridge,\r
546 Mem32Bridge,\r
547 PMem32Bridge,\r
548 Mem64Bridge,\r
549 PMem64Bridge,\r
550 &AcpiConfig\r
551 );\r
552\r
553 //\r
554 // Insert these resource nodes into the database\r
555 //\r
556 InsertResourceNode (&IoPool, IoBridge);\r
557 InsertResourceNode (&Mem32Pool, Mem32Bridge);\r
558 InsertResourceNode (&PMem32Pool, PMem32Bridge);\r
559 InsertResourceNode (&Mem64Pool, Mem64Bridge);\r
560 InsertResourceNode (&PMem64Pool, PMem64Bridge);\r
561\r
562 if (Status == EFI_SUCCESS) {\r
563 //\r
564 // Submit the resource requirement\r
565 //\r
566 Status = PciResAlloc->SubmitResources (\r
567 PciResAlloc,\r
568 RootBridgeDev->Handle,\r
569 AcpiConfig\r
570 );\r
571 }\r
572\r
573 //\r
574 // Free acpi resource node\r
575 //\r
576 if (AcpiConfig != NULL) {\r
577 FreePool (AcpiConfig);\r
578 }\r
579\r
580 if (EFI_ERROR (Status)) {\r
581 //\r
582 // Destroy all the resource tree\r
583 //\r
584 DestroyResourceTree (&IoPool);\r
585 DestroyResourceTree (&Mem32Pool);\r
586 DestroyResourceTree (&PMem32Pool);\r
587 DestroyResourceTree (&Mem64Pool);\r
588 DestroyResourceTree (&PMem64Pool);\r
589 return Status;\r
590 }\r
591 }\r
592 //\r
593 // End while, at least one Root Bridge should be found.\r
594 //\r
595 ASSERT (RootBridgeDev != NULL);\r
596\r
597 //\r
598 // Notify platform to start to program the resource\r
599 //\r
600 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);\r
601 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
602 //\r
603 // If Hot Plug is not supported\r
604 //\r
605 if (EFI_ERROR (Status)) {\r
606 //\r
607 // Allocation failed, then return\r
608 //\r
609 return EFI_OUT_OF_RESOURCES;\r
610 }\r
611 //\r
612 // Allocation succeed.\r
613 // Get host bridge handle for status report, and then skip the main while\r
614 //\r
615 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
616\r
617 break;\r
618\r
619 } else {\r
620 //\r
621 // If Hot Plug is supported\r
622 //\r
623 if (!EFI_ERROR (Status)) {\r
624 //\r
625 // Allocation succeed, then continue the following\r
626 //\r
627 break;\r
628 }\r
629\r
630 //\r
631 // If the resource allocation is unsuccessful, free resources on bridge\r
632 //\r
633\r
634 RootBridgeDev = NULL;\r
635 RootBridgeHandle = 0;\r
636\r
637 IoResStatus = EFI_RESOURCE_SATISFIED;\r
638 Mem32ResStatus = EFI_RESOURCE_SATISFIED;\r
639 PMem32ResStatus = EFI_RESOURCE_SATISFIED;\r
640 Mem64ResStatus = EFI_RESOURCE_SATISFIED;\r
641 PMem64ResStatus = EFI_RESOURCE_SATISFIED;\r
642\r
643 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
644 //\r
645 // Get RootBridg Device by handle\r
646 //\r
647 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
648 if (RootBridgeDev == NULL) {\r
649 return EFI_NOT_FOUND;\r
650 }\r
651\r
652 //\r
653 // Get host bridge handle for status report\r
654 //\r
655 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
656\r
657 //\r
658 // Get acpi resource node for all the resource types\r
659 //\r
660 AcpiConfig = NULL;\r
661\r
662 Status = PciResAlloc->GetProposedResources (\r
663 PciResAlloc,\r
664 RootBridgeDev->Handle,\r
665 &AcpiConfig\r
666 );\r
667\r
668 if (EFI_ERROR (Status)) {\r
669 return Status;\r
670 }\r
671\r
672 if (AcpiConfig != NULL) {\r
673 //\r
674 // Adjust resource allocation policy for each RB\r
675 //\r
676 GetResourceAllocationStatus (\r
677 AcpiConfig,\r
678 &IoResStatus,\r
679 &Mem32ResStatus,\r
680 &PMem32ResStatus,\r
681 &Mem64ResStatus,\r
682 &PMem64ResStatus\r
683 );\r
684 FreePool (AcpiConfig);\r
685 }\r
686 }\r
687 //\r
688 // End while\r
689 //\r
690\r
691 //\r
692 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code\r
693 //\r
694 //\r
695 // It is very difficult to follow the spec here\r
696 // Device path , Bar index can not be get here\r
697 //\r
698 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));\r
699\r
700 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
701 EFI_PROGRESS_CODE,\r
702 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,\r
703 (VOID *) &AllocFailExtendedData,\r
704 sizeof (AllocFailExtendedData)\r
705 );\r
706\r
707 Status = PciHostBridgeAdjustAllocation (\r
708 &IoPool,\r
709 &Mem32Pool,\r
710 &PMem32Pool,\r
711 &Mem64Pool,\r
712 &PMem64Pool,\r
713 IoResStatus,\r
714 Mem32ResStatus,\r
715 PMem32ResStatus,\r
716 Mem64ResStatus,\r
717 PMem64ResStatus\r
718 );\r
719\r
720 //\r
721 // Destroy all the resource tree\r
722 //\r
723 DestroyResourceTree (&IoPool);\r
724 DestroyResourceTree (&Mem32Pool);\r
725 DestroyResourceTree (&PMem32Pool);\r
726 DestroyResourceTree (&Mem64Pool);\r
727 DestroyResourceTree (&PMem64Pool);\r
728\r
729 NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);\r
730\r
731 if (EFI_ERROR (Status)) {\r
732 return Status;\r
733 }\r
734\r
735 ReAllocate = TRUE;\r
736 }\r
737 }\r
738 //\r
739 // End main while\r
740 //\r
741\r
742 //\r
743 // Raise the EFI_IOB_PCI_RES_ALLOC status code\r
744 //\r
745 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
746 EFI_PROGRESS_CODE,\r
fe91c992 747 EFI_IO_BUS_PCI | EFI_IOB_PCI_RES_ALLOC,\r
9060e3ec 748 (VOID *) &HandleExtendedData,\r
749 sizeof (HandleExtendedData)\r
750 );\r
751\r
752 //\r
753 // Notify pci bus driver starts to program the resource\r
754 //\r
755 NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);\r
756\r
757 RootBridgeDev = NULL;\r
758\r
759 RootBridgeHandle = 0;\r
760\r
761 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
762 //\r
763 // Get RootBridg Device by handle\r
764 //\r
765 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
766\r
767 if (RootBridgeDev == NULL) {\r
768 return EFI_NOT_FOUND;\r
769 }\r
770\r
771 //\r
772 // Get acpi resource node for all the resource types\r
773 //\r
774 AcpiConfig = NULL;\r
775 Status = PciResAlloc->GetProposedResources (\r
776 PciResAlloc,\r
777 RootBridgeDev->Handle,\r
778 &AcpiConfig\r
779 );\r
780\r
781 if (EFI_ERROR (Status)) {\r
782 return Status;\r
783 }\r
784\r
785 //\r
786 // Get the resource base by interpreting acpi resource node\r
787 //\r
788 //\r
789 GetResourceBase (\r
790 AcpiConfig,\r
791 &IoBase,\r
792 &Mem32Base,\r
793 &PMem32Base,\r
794 &Mem64Base,\r
795 &PMem64Base\r
796 );\r
797\r
798 //\r
799 // Process option rom for this root bridge\r
800 //\r
801 ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);\r
802\r
803 //\r
804 // Create the entire system resource map from the information collected by\r
805 // enumerator. Several resource tree was created\r
806 //\r
8db6a82c
RN
807 IoBridge = FindResourceNode (RootBridgeDev, &IoPool);\r
808 Mem32Bridge = FindResourceNode (RootBridgeDev, &Mem32Pool);\r
809 PMem32Bridge = FindResourceNode (RootBridgeDev, &PMem32Pool);\r
810 Mem64Bridge = FindResourceNode (RootBridgeDev, &Mem64Pool);\r
811 PMem64Bridge = FindResourceNode (RootBridgeDev, &PMem64Pool);\r
9060e3ec 812\r
9995c2e5
RN
813 ASSERT (IoBridge != NULL);\r
814 ASSERT (Mem32Bridge != NULL);\r
815 ASSERT (PMem32Bridge != NULL);\r
816 ASSERT (Mem64Bridge != NULL);\r
817 ASSERT (PMem64Bridge != NULL);\r
818\r
9060e3ec 819 //\r
820 // Program IO resources\r
821 //\r
822 ProgramResource (\r
823 IoBase,\r
824 IoBridge\r
825 );\r
826\r
827 //\r
828 // Program Mem32 resources\r
829 //\r
830 ProgramResource (\r
831 Mem32Base,\r
832 Mem32Bridge\r
833 );\r
834\r
835 //\r
836 // Program PMem32 resources\r
837 //\r
838 ProgramResource (\r
839 PMem32Base,\r
840 PMem32Bridge\r
841 );\r
842\r
843 //\r
844 // Program Mem64 resources\r
845 //\r
846 ProgramResource (\r
847 Mem64Base,\r
848 Mem64Bridge\r
849 );\r
850\r
851 //\r
852 // Program PMem64 resources\r
853 //\r
854 ProgramResource (\r
855 PMem64Base,\r
856 PMem64Bridge\r
857 );\r
858\r
8db6a82c
RN
859 IoBridge ->PciDev->PciBar[IoBridge ->Bar].BaseAddress = IoBase;\r
860 Mem32Bridge ->PciDev->PciBar[Mem32Bridge ->Bar].BaseAddress = Mem32Base;\r
861 PMem32Bridge->PciDev->PciBar[PMem32Bridge->Bar].BaseAddress = PMem32Base;\r
862 Mem64Bridge ->PciDev->PciBar[Mem64Bridge ->Bar].BaseAddress = Mem64Base;\r
863 PMem64Bridge->PciDev->PciBar[PMem64Bridge->Bar].BaseAddress = PMem64Base;\r
864\r
865 //\r
866 // Dump the resource map for current root bridge\r
867 //\r
868 DEBUG_CODE (\r
869 DumpResourceMap (\r
870 RootBridgeDev,\r
871 IoBridge,\r
872 Mem32Bridge,\r
873 PMem32Bridge,\r
874 Mem64Bridge,\r
875 PMem64Bridge\r
876 );\r
877 );\r
878\r
9060e3ec 879 FreePool (AcpiConfig);\r
880 }\r
881\r
882 //\r
883 // Destroy all the resource tree\r
884 //\r
885 DestroyResourceTree (&IoPool);\r
886 DestroyResourceTree (&Mem32Pool);\r
887 DestroyResourceTree (&PMem32Pool);\r
888 DestroyResourceTree (&Mem64Pool);\r
889 DestroyResourceTree (&PMem64Pool);\r
890\r
891 //\r
892 // Notify the resource allocation phase is to end\r
893 //\r
894 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);\r
895\r
896 return EFI_SUCCESS;\r
897}\r
898\r
899/**\r
900 Scan pci bus and assign bus number to the given PCI bus system.\r
901\r
902 @param Bridge Bridge device instance.\r
903 @param StartBusNumber start point.\r
904 @param SubBusNumber Point to sub bus number.\r
905 @param PaddedBusRange Customized bus number.\r
906\r
907 @retval EFI_SUCCESS Successfully scanned and assigned bus number.\r
908 @retval other Some error occurred when scanning pci bus.\r
909\r
910 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
911\r
912**/\r
913EFI_STATUS\r
914PciScanBus (\r
915 IN PCI_IO_DEVICE *Bridge,\r
916 IN UINT8 StartBusNumber,\r
917 OUT UINT8 *SubBusNumber,\r
918 OUT UINT8 *PaddedBusRange\r
919 )\r
920{\r
921 EFI_STATUS Status;\r
922 PCI_TYPE00 Pci;\r
923 UINT8 Device;\r
924 UINT8 Func;\r
925 UINT64 Address;\r
926 UINTN SecondBus;\r
927 UINT16 Register;\r
928 UINTN HpIndex;\r
929 PCI_IO_DEVICE *PciDevice;\r
930 EFI_EVENT Event;\r
931 EFI_HPC_STATE State;\r
932 UINT64 PciAddress;\r
933 EFI_HPC_PADDING_ATTRIBUTES Attributes;\r
934 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
935 UINT16 BusRange;\r
936 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
937 BOOLEAN BusPadding;\r
938 UINT32 TempReservedBusNum;\r
939\r
940 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
941 SecondBus = 0;\r
942 Register = 0;\r
943 State = 0;\r
944 Attributes = (EFI_HPC_PADDING_ATTRIBUTES) 0;\r
945 BusRange = 0;\r
946 BusPadding = FALSE;\r
947 PciDevice = NULL;\r
948 PciAddress = 0;\r
949\r
950 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
951 TempReservedBusNum = 0;\r
952 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
953\r
954 //\r
955 // Check to see whether a pci device is present\r
956 //\r
957 Status = PciDevicePresent (\r
958 PciRootBridgeIo,\r
959 &Pci,\r
960 StartBusNumber,\r
961 Device,\r
962 Func\r
963 );\r
964\r
965 if (EFI_ERROR (Status)) {\r
9060e3ec 966 continue;\r
967 }\r
968\r
d4048391 969 //\r
970 // Get the PCI device information\r
971 //\r
972 Status = PciSearchDevice (\r
973 Bridge,\r
974 &Pci,\r
975 StartBusNumber,\r
976 Device,\r
977 Func,\r
978 &PciDevice\r
979 );\r
9060e3ec 980\r
d4048391 981 ASSERT (!EFI_ERROR (Status));\r
9060e3ec 982\r
d4048391 983 PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);\r
9060e3ec 984\r
d4048391 985 if (!IS_PCI_BRIDGE (&Pci)) {\r
986 //\r
987 // PCI bridges will be called later\r
988 // Here just need for PCI device or PCI to cardbus controller\r
989 // EfiPciBeforeChildBusEnumeration for PCI Device Node\r
990 //\r
991 PreprocessController (\r
992 PciDevice,\r
993 PciDevice->BusNumber,\r
994 PciDevice->DeviceNumber,\r
995 PciDevice->FunctionNumber,\r
996 EfiPciBeforeChildBusEnumeration\r
997 );\r
998 }\r
9060e3ec 999\r
d4048391 1000 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
9060e3ec 1001 //\r
1002 // For Pci Hotplug controller devcie only\r
1003 //\r
1004 if (gPciHotPlugInit != NULL) {\r
1005 //\r
1006 // Check if it is a Hotplug PCI controller\r
1007 //\r
1008 if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {\r
55565b08 1009 gPciRootHpcData[HpIndex].Found = TRUE;\r
9060e3ec 1010\r
1011 if (!gPciRootHpcData[HpIndex].Initialized) {\r
1012\r
1013 Status = CreateEventForHpc (HpIndex, &Event);\r
1014\r
1015 ASSERT (!EFI_ERROR (Status));\r
1016\r
1017 Status = gPciHotPlugInit->InitializeRootHpc (\r
1018 gPciHotPlugInit,\r
1019 gPciRootHpcPool[HpIndex].HpcDevicePath,\r
1020 PciAddress,\r
1021 Event,\r
1022 &State\r
1023 );\r
1024\r
1025 PreprocessController (\r
1026 PciDevice,\r
1027 PciDevice->BusNumber,\r
1028 PciDevice->DeviceNumber,\r
1029 PciDevice->FunctionNumber,\r
1030 EfiPciBeforeChildBusEnumeration\r
1031 );\r
1032 }\r
1033 }\r
1034 }\r
1035 }\r
1036\r
1037 if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {\r
1038 //\r
1039 // For PPB\r
1040 //\r
1041 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1042 //\r
1043 // If Hot Plug is not supported,\r
1044 // get the bridge information\r
1045 //\r
1046 Status = PciSearchDevice (\r
1047 Bridge,\r
1048 &Pci,\r
1049 StartBusNumber,\r
1050 Device,\r
1051 Func,\r
1052 &PciDevice\r
1053 );\r
1054\r
1055 if (EFI_ERROR (Status)) {\r
1056 return Status;\r
1057 }\r
1058 } else {\r
1059 //\r
1060 // If Hot Plug is supported,\r
1061 // Get the bridge information\r
1062 //\r
1063 BusPadding = FALSE;\r
1064 if (gPciHotPlugInit != NULL) {\r
1065\r
1066 if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {\r
1067\r
1068 //\r
1069 // If it is initialized, get the padded bus range\r
1070 //\r
1071 Status = gPciHotPlugInit->GetResourcePadding (\r
1072 gPciHotPlugInit,\r
1073 gPciRootHpcPool[HpIndex].HpbDevicePath,\r
1074 PciAddress,\r
1075 &State,\r
1076 (VOID **) &Descriptors,\r
1077 &Attributes\r
1078 );\r
1079\r
1080 if (EFI_ERROR (Status)) {\r
1081 return Status;\r
1082 }\r
1083\r
1084 BusRange = 0;\r
1085 Status = PciGetBusRange (\r
1086 &Descriptors,\r
1087 NULL,\r
1088 NULL,\r
1089 &BusRange\r
1090 );\r
1091\r
1092 FreePool (Descriptors);\r
1093\r
1094 if (EFI_ERROR (Status)) {\r
1095 return Status;\r
1096 }\r
1097\r
1098 BusPadding = TRUE;\r
1099 }\r
1100 }\r
1101 }\r
1102\r
1103 //\r
1104 // Add feature to support customized secondary bus number\r
1105 //\r
1106 if (*SubBusNumber == 0) {\r
1107 *SubBusNumber = *PaddedBusRange;\r
1108 *PaddedBusRange = 0;\r
1109 }\r
1110\r
1111 (*SubBusNumber)++;\r
1112 SecondBus = *SubBusNumber;\r
1113\r
1114 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
1115 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET);\r
1116\r
1117 Status = PciRootBridgeIo->Pci.Write (\r
1118 PciRootBridgeIo,\r
1119 EfiPciWidthUint16,\r
1120 Address,\r
1121 1,\r
1122 &Register\r
1123 );\r
1124\r
1125\r
1126 //\r
1127 // If it is PPB, resursively search down this bridge\r
1128 //\r
1129 if (IS_PCI_BRIDGE (&Pci)) {\r
1130\r
1131 //\r
1132 // Temporarily initialize SubBusNumber to maximum bus number to ensure the\r
1133 // PCI configuration transaction to go through any PPB\r
1134 //\r
1135 Register = 0xFF;\r
1136 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
1137 Status = PciRootBridgeIo->Pci.Write (\r
1138 PciRootBridgeIo,\r
1139 EfiPciWidthUint8,\r
1140 Address,\r
1141 1,\r
1142 &Register\r
1143 );\r
1144\r
1145 //\r
1146 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige\r
1147 //\r
1148 PreprocessController (\r
1149 PciDevice,\r
1150 PciDevice->BusNumber,\r
1151 PciDevice->DeviceNumber,\r
1152 PciDevice->FunctionNumber,\r
1153 EfiPciBeforeChildBusEnumeration\r
1154 );\r
1155\r
9060e3ec 1156 Status = PciScanBus (\r
1157 PciDevice,\r
1158 (UINT8) (SecondBus),\r
1159 SubBusNumber,\r
1160 PaddedBusRange\r
1161 );\r
1162 if (EFI_ERROR (Status)) {\r
1163 return Status;\r
1164 }\r
1165 }\r
1166\r
1167 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport) && BusPadding) {\r
1168 //\r
1169 // Ensure the device is enabled and initialized\r
1170 //\r
1171 if ((Attributes == EfiPaddingPciRootBridge) &&\r
1172 (State & EFI_HPC_STATE_ENABLED) != 0 &&\r
1173 (State & EFI_HPC_STATE_INITIALIZED) != 0) {\r
1174 *PaddedBusRange = (UINT8) ((UINT8) (BusRange) +*PaddedBusRange);\r
1175 } else {\r
1176 *SubBusNumber = (UINT8) ((UINT8) (BusRange) +*SubBusNumber);\r
1177 }\r
1178 }\r
1179\r
1180 //\r
1181 // Set the current maximum bus number under the PPB\r
1182 //\r
1183 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
1184\r
1185 Status = PciRootBridgeIo->Pci.Write (\r
1186 PciRootBridgeIo,\r
1187 EfiPciWidthUint8,\r
1188 Address,\r
1189 1,\r
1190 SubBusNumber\r
1191 );\r
1192 } else {\r
1193 //\r
1194 // It is device. Check PCI IOV for Bus reservation\r
9060e3ec 1195 // Go through each function, just reserve the MAX ReservedBusNum for one device\r
1196 //\r
d4048391 1197 if (PcdGetBool (PcdSrIovSupport) && PciDevice->SrIovCapabilityOffset != 0) {\r
9060e3ec 1198 if (TempReservedBusNum < PciDevice->ReservedBusNum) {\r
1199\r
1200 (*SubBusNumber) = (UINT8)((*SubBusNumber) + PciDevice->ReservedBusNum - TempReservedBusNum);\r
1201 TempReservedBusNum = PciDevice->ReservedBusNum;\r
1202\r
1203 if (Func == 0) {\r
1204 DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber));\r
1205 } else {\r
1206 DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber));\r
1207 }\r
1208 }\r
1209 }\r
1210 }\r
1211\r
1212 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
1213\r
1214 //\r
1215 // Skip sub functions, this is not a multi function device\r
1216 //\r
1217\r
1218 Func = PCI_MAX_FUNC;\r
1219 }\r
1220 }\r
1221 }\r
1222\r
1223 return EFI_SUCCESS;\r
1224}\r
1225\r
1226/**\r
1227 Process Option Rom on the specified root bridge.\r
1228\r
1229 @param Bridge Pci root bridge device instance.\r
1230\r
1231 @retval EFI_SUCCESS Success process.\r
1232 @retval other Some error occurred when processing Option Rom on the root bridge.\r
1233\r
1234**/\r
1235EFI_STATUS\r
1236PciRootBridgeP2CProcess (\r
1237 IN PCI_IO_DEVICE *Bridge\r
1238 )\r
1239{\r
1240 LIST_ENTRY *CurrentLink;\r
1241 PCI_IO_DEVICE *Temp;\r
1242 EFI_HPC_STATE State;\r
1243 UINT64 PciAddress;\r
1244 EFI_STATUS Status;\r
1245\r
1246 CurrentLink = Bridge->ChildList.ForwardLink;\r
1247\r
1248 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
1249\r
1250 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1251\r
1252 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
1253\r
1254 if (gPciHotPlugInit != NULL && Temp->Allocated && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1255\r
1256 //\r
1257 // Raise the EFI_IOB_PCI_HPC_INIT status code\r
1258 //\r
1259 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1260 EFI_PROGRESS_CODE,\r
fe91c992 1261 EFI_IO_BUS_PCI | EFI_IOB_PCI_HPC_INIT,\r
9060e3ec 1262 Temp->DevicePath\r
1263 );\r
1264\r
1265 PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);\r
1266 Status = gPciHotPlugInit->InitializeRootHpc (\r
1267 gPciHotPlugInit,\r
1268 Temp->DevicePath,\r
1269 PciAddress,\r
1270 NULL,\r
1271 &State\r
1272 );\r
1273\r
1274 if (!EFI_ERROR (Status)) {\r
1275 Status = PciBridgeEnumerator (Temp);\r
1276\r
1277 if (EFI_ERROR (Status)) {\r
1278 return Status;\r
1279 }\r
1280 }\r
1281\r
1282 CurrentLink = CurrentLink->ForwardLink;\r
1283 continue;\r
1284\r
1285 }\r
1286 }\r
1287\r
1288 if (!IsListEmpty (&Temp->ChildList)) {\r
1289 Status = PciRootBridgeP2CProcess (Temp);\r
1290 }\r
1291\r
1292 CurrentLink = CurrentLink->ForwardLink;\r
1293 }\r
1294\r
1295 return EFI_SUCCESS;\r
1296}\r
1297\r
1298/**\r
1299 Process Option Rom on the specified host bridge.\r
1300\r
1301 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
1302\r
1303 @retval EFI_SUCCESS Success process.\r
1304 @retval EFI_NOT_FOUND Can not find the root bridge instance.\r
1305 @retval other Some error occurred when processing Option Rom on the host bridge.\r
1306\r
1307**/\r
1308EFI_STATUS\r
1309PciHostBridgeP2CProcess (\r
1310 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1311 )\r
1312{\r
1313 EFI_HANDLE RootBridgeHandle;\r
1314 PCI_IO_DEVICE *RootBridgeDev;\r
1315 EFI_STATUS Status;\r
1316\r
1317 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1318 return EFI_SUCCESS;\r
1319 }\r
1320\r
1321 RootBridgeHandle = NULL;\r
1322\r
1323 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1324\r
1325 //\r
1326 // Get RootBridg Device by handle\r
1327 //\r
1328 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
1329\r
1330 if (RootBridgeDev == NULL) {\r
1331 return EFI_NOT_FOUND;\r
1332 }\r
1333\r
1334 Status = PciRootBridgeP2CProcess (RootBridgeDev);\r
1335 if (EFI_ERROR (Status)) {\r
1336 return Status;\r
1337 }\r
1338\r
1339 }\r
1340\r
1341 return EFI_SUCCESS;\r
1342}\r
1343\r
1344/**\r
1345 This function is used to enumerate the entire host bridge\r
1346 in a given platform.\r
1347\r
1348 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.\r
1349\r
1350 @retval EFI_SUCCESS Successfully enumerated the host bridge.\r
1351 @retval EFI_OUT_OF_RESOURCES No enough memory available.\r
1352 @retval other Some error occurred when enumerating the host bridge.\r
1353\r
1354**/\r
1355EFI_STATUS\r
1356PciHostBridgeEnumerator (\r
1357 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1358 )\r
1359{\r
1360 EFI_HANDLE RootBridgeHandle;\r
1361 PCI_IO_DEVICE *RootBridgeDev;\r
1362 EFI_STATUS Status;\r
1363 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1364 UINT16 MinBus;\r
1365 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1366 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
1367 UINT8 StartBusNumber;\r
1368 LIST_ENTRY RootBridgeList;\r
1369 LIST_ENTRY *Link;\r
1370\r
1371 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1372 InitializeHotPlugSupport ();\r
1373 }\r
1374\r
1375 InitializeListHead (&RootBridgeList);\r
1376\r
1377 //\r
1378 // Notify the bus allocation phase is about to start\r
1379 //\r
1380 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1381\r
1382 DEBUG((EFI_D_INFO, "PCI Bus First Scanning\n"));\r
1383 RootBridgeHandle = NULL;\r
1384 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1385\r
1386 //\r
1387 // if a root bridge instance is found, create root bridge device for it\r
1388 //\r
1389\r
1390 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1391\r
1392 if (RootBridgeDev == NULL) {\r
1393 return EFI_OUT_OF_RESOURCES;\r
1394 }\r
1395\r
1396 //\r
1397 // Enumerate all the buses under this root bridge\r
1398 //\r
1399 Status = PciRootBridgeEnumerator (\r
1400 PciResAlloc,\r
1401 RootBridgeDev\r
1402 );\r
1403\r
1404 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1405 InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));\r
1406 } else {\r
1407 DestroyRootBridge (RootBridgeDev);\r
1408 }\r
1409 if (EFI_ERROR (Status)) {\r
1410 return Status;\r
1411 }\r
1412 }\r
1413\r
1414 //\r
1415 // Notify the bus allocation phase is finished for the first time\r
1416 //\r
1417 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1418\r
1419 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1420 //\r
1421 // Reset all assigned PCI bus number in all PPB\r
1422 //\r
1423 RootBridgeHandle = NULL;\r
1424 Link = GetFirstNode (&RootBridgeList);\r
1425 while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&\r
1426 (!IsNull (&RootBridgeList, Link))) {\r
1427 RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);\r
1428 //\r
1429 // Get the Bus information\r
1430 //\r
1431 Status = PciResAlloc->StartBusEnumeration (\r
1432 PciResAlloc,\r
1433 RootBridgeHandle,\r
1434 (VOID **) &Configuration\r
1435 );\r
1436 if (EFI_ERROR (Status)) {\r
1437 return Status;\r
1438 }\r
1439\r
1440 //\r
1441 // Get the bus number to start with\r
1442 //\r
1443 StartBusNumber = (UINT8) (Configuration->AddrRangeMin);\r
1444\r
1445 ResetAllPpbBusNumber (\r
1446 RootBridgeDev,\r
1447 StartBusNumber\r
1448 );\r
1449\r
1450 FreePool (Configuration);\r
8063b47b 1451 Link = RemoveEntryList (Link);\r
9060e3ec 1452 DestroyRootBridge (RootBridgeDev);\r
1453 }\r
1454\r
1455 //\r
1456 // Wait for all HPC initialized\r
1457 //\r
1458 Status = AllRootHPCInitialized (STALL_1_SECOND * 15);\r
1459\r
1460 if (EFI_ERROR (Status)) {\r
55565b08 1461 DEBUG ((EFI_D_ERROR, "Some root HPC failed to initialize\n"));\r
9060e3ec 1462 return Status;\r
1463 }\r
1464\r
1465 //\r
1466 // Notify the bus allocation phase is about to start for the 2nd time\r
1467 //\r
1468 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1469\r
1470 DEBUG((EFI_D_INFO, "PCI Bus Second Scanning\n"));\r
1471 RootBridgeHandle = NULL;\r
1472 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1473\r
1474 //\r
1475 // if a root bridge instance is found, create root bridge device for it\r
1476 //\r
1477 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1478\r
1479 if (RootBridgeDev == NULL) {\r
1480 return EFI_OUT_OF_RESOURCES;\r
1481 }\r
1482\r
1483 //\r
1484 // Enumerate all the buses under this root bridge\r
1485 //\r
1486 Status = PciRootBridgeEnumerator (\r
1487 PciResAlloc,\r
1488 RootBridgeDev\r
1489 );\r
1490\r
1491 DestroyRootBridge (RootBridgeDev);\r
1492 if (EFI_ERROR (Status)) {\r
1493 return Status;\r
1494 }\r
1495 }\r
1496\r
1497 //\r
1498 // Notify the bus allocation phase is to end for the 2nd time\r
1499 //\r
1500 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1501 }\r
1502\r
1503 //\r
1504 // Notify the resource allocation phase is to start\r
1505 //\r
1506 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);\r
1507\r
1508 RootBridgeHandle = NULL;\r
1509 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1510\r
1511 //\r
1512 // if a root bridge instance is found, create root bridge device for it\r
1513 //\r
1514 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1515\r
1516 if (RootBridgeDev == NULL) {\r
1517 return EFI_OUT_OF_RESOURCES;\r
1518 }\r
1519\r
1520 Status = StartManagingRootBridge (RootBridgeDev);\r
1521\r
1522 if (EFI_ERROR (Status)) {\r
1523 return Status;\r
1524 }\r
1525\r
1526 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;\r
1527 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
1528\r
1529 if (EFI_ERROR (Status)) {\r
1530 return Status;\r
1531 }\r
1532\r
1533 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);\r
1534\r
1535 if (EFI_ERROR (Status)) {\r
1536 return Status;\r
1537 }\r
1538\r
1539 //\r
1540 // Determine root bridge attribute by calling interface of Pcihostbridge\r
1541 // protocol\r
1542 //\r
1543 DetermineRootBridgeAttributes (\r
1544 PciResAlloc,\r
1545 RootBridgeDev\r
1546 );\r
1547\r
1548 //\r
1549 // Collect all the resource information under this root bridge\r
1550 // A database that records all the information about pci device subject to this\r
1551 // root bridge will then be created\r
1552 //\r
1553 Status = PciPciDeviceInfoCollector (\r
1554 RootBridgeDev,\r
1555 (UINT8) MinBus\r
1556 );\r
1557\r
1558 if (EFI_ERROR (Status)) {\r
1559 return Status;\r
1560 }\r
1561\r
1562 InsertRootBridge (RootBridgeDev);\r
1563\r
1564 //\r
1565 // Record the hostbridge handle\r
1566 //\r
1567 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);\r
1568 }\r
1569\r
1570 return EFI_SUCCESS;\r
1571}\r