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