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