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