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