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