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