]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciEnumeratorSupport.c
1 /** @file
2 PCI emumeration support functions 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 Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include "PciBus.h"
12
13 extern CHAR16 *mBarTypeStr[];
14 extern EDKII_DEVICE_SECURITY_PROTOCOL *mDeviceSecurityProtocol;
15
16 #define OLD_ALIGN 0xFFFFFFFFFFFFFFFFULL
17 #define EVEN_ALIGN 0xFFFFFFFFFFFFFFFEULL
18 #define SQUAD_ALIGN 0xFFFFFFFFFFFFFFFDULL
19 #define DQUAD_ALIGN 0xFFFFFFFFFFFFFFFCULL
20
21 /**
22 This routine is used to check whether the pci device is present.
23
24 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
25 @param Pci Output buffer for PCI device configuration space.
26 @param Bus PCI bus NO.
27 @param Device PCI device NO.
28 @param Func PCI Func NO.
29
30 @retval EFI_NOT_FOUND PCI device not present.
31 @retval EFI_SUCCESS PCI device is found.
32
33 **/
34 EFI_STATUS
35 PciDevicePresent (
36 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
37 OUT PCI_TYPE00 *Pci,
38 IN UINT8 Bus,
39 IN UINT8 Device,
40 IN UINT8 Func
41 )
42 {
43 UINT64 Address;
44 EFI_STATUS Status;
45
46 //
47 // Create PCI address map in terms of Bus, Device and Func
48 //
49 Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
50
51 //
52 // Read the Vendor ID register
53 //
54 Status = PciRootBridgeIo->Pci.Read (
55 PciRootBridgeIo,
56 EfiPciWidthUint32,
57 Address,
58 1,
59 Pci
60 );
61
62 if (!EFI_ERROR (Status) && ((Pci->Hdr).VendorId != 0xffff)) {
63 //
64 // Read the entire config header for the device
65 //
66 Status = PciRootBridgeIo->Pci.Read (
67 PciRootBridgeIo,
68 EfiPciWidthUint32,
69 Address,
70 sizeof (PCI_TYPE00) / sizeof (UINT32),
71 Pci
72 );
73
74 return EFI_SUCCESS;
75 }
76
77 return EFI_NOT_FOUND;
78 }
79
80 /**
81 Collect all the resource information under this root bridge.
82
83 A database that records all the information about pci device subject to this
84 root bridge will then be created.
85
86 @param Bridge Parent bridge instance.
87 @param StartBusNumber Bus number of beginning.
88
89 @retval EFI_SUCCESS PCI device is found.
90 @retval other Some error occurred when reading PCI bridge information.
91
92 **/
93 EFI_STATUS
94 PciPciDeviceInfoCollector (
95 IN PCI_IO_DEVICE *Bridge,
96 IN UINT8 StartBusNumber
97 )
98 {
99 EFI_STATUS Status;
100 PCI_TYPE00 Pci;
101 UINT8 Device;
102 UINT8 Func;
103 UINT8 SecBus;
104 PCI_IO_DEVICE *PciIoDevice;
105 EFI_PCI_IO_PROTOCOL *PciIo;
106
107 Status = EFI_SUCCESS;
108 SecBus = 0;
109
110 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
111 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
112 //
113 // Check to see whether PCI device is present
114 //
115 Status = PciDevicePresent (
116 Bridge->PciRootBridgeIo,
117 &Pci,
118 (UINT8)StartBusNumber,
119 (UINT8)Device,
120 (UINT8)Func
121 );
122
123 if (EFI_ERROR (Status) && (Func == 0)) {
124 //
125 // go to next device if there is no Function 0
126 //
127 break;
128 }
129
130 if (!EFI_ERROR (Status)) {
131 //
132 // Call back to host bridge function
133 //
134 PreprocessController (Bridge, (UINT8)StartBusNumber, Device, Func, EfiPciBeforeResourceCollection);
135
136 //
137 // Collect all the information about the PCI device discovered
138 //
139 Status = PciSearchDevice (
140 Bridge,
141 &Pci,
142 (UINT8)StartBusNumber,
143 Device,
144 Func,
145 &PciIoDevice
146 );
147
148 //
149 // Recursively scan PCI busses on the other side of PCI-PCI bridges
150 //
151 //
152 if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {
153 //
154 // If it is PPB, we need to get the secondary bus to continue the enumeration
155 //
156 PciIo = &(PciIoDevice->PciIo);
157
158 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, 1, &SecBus);
159
160 if (EFI_ERROR (Status)) {
161 return Status;
162 }
163
164 //
165 // Ensure secondary bus number is greater than the primary bus number to avoid
166 // any potential dead loop when PcdPciDisableBusEnumeration is set to TRUE
167 //
168 if (SecBus <= StartBusNumber) {
169 break;
170 }
171
172 //
173 // Get resource padding for PPB
174 //
175 GetResourcePaddingPpb (PciIoDevice);
176
177 //
178 // Deep enumerate the next level bus
179 //
180 Status = PciPciDeviceInfoCollector (
181 PciIoDevice,
182 (UINT8)(SecBus)
183 );
184 }
185
186 if ((Func == 0) && !IS_PCI_MULTI_FUNC (&Pci)) {
187 //
188 // Skip sub functions, this is not a multi function device
189 //
190 Func = PCI_MAX_FUNC;
191 }
192 }
193 }
194 }
195
196 return EFI_SUCCESS;
197 }
198
199 /**
200 Search required device and create PCI device instance.
201
202 @param Bridge Parent bridge instance.
203 @param Pci Input PCI device information block.
204 @param Bus PCI bus NO.
205 @param Device PCI device NO.
206 @param Func PCI func NO.
207 @param PciDevice Output of searched PCI device instance.
208
209 @retval EFI_SUCCESS Successfully created PCI device instance.
210 @retval EFI_OUT_OF_RESOURCES Cannot get PCI device information.
211
212 **/
213 EFI_STATUS
214 PciSearchDevice (
215 IN PCI_IO_DEVICE *Bridge,
216 IN PCI_TYPE00 *Pci,
217 IN UINT8 Bus,
218 IN UINT8 Device,
219 IN UINT8 Func,
220 OUT PCI_IO_DEVICE **PciDevice
221 )
222 {
223 PCI_IO_DEVICE *PciIoDevice;
224 BOOLEAN IgnoreOptionRom;
225
226 PciIoDevice = NULL;
227 IgnoreOptionRom = FALSE;
228
229 DEBUG ((
230 DEBUG_INFO,
231 "PciBus: Discovered %s @ [%02x|%02x|%02x] [VID = 0x%x, DID = 0x%0x]\n",
232 IS_PCI_BRIDGE (Pci) ? L"PPB" :
233 IS_CARDBUS_BRIDGE (Pci) ? L"P2C" :
234 L"PCI",
235 Bus,
236 Device,
237 Func,
238 Pci->Hdr.VendorId,
239 Pci->Hdr.DeviceId
240 ));
241
242 if (!IS_PCI_BRIDGE (Pci)) {
243 if (IS_CARDBUS_BRIDGE (Pci)) {
244 PciIoDevice = GatherP2CInfo (
245 Bridge,
246 Pci,
247 Bus,
248 Device,
249 Func
250 );
251 if ((PciIoDevice != NULL) && gFullEnumeration) {
252 InitializeP2C (PciIoDevice);
253 }
254 } else {
255 //
256 // Create private data for Pci Device
257 //
258 PciIoDevice = GatherDeviceInfo (
259 Bridge,
260 Pci,
261 Bus,
262 Device,
263 Func
264 );
265 }
266 } else {
267 //
268 // Create private data for PPB
269 //
270 PciIoDevice = GatherPpbInfo (
271 Bridge,
272 Pci,
273 Bus,
274 Device,
275 Func
276 );
277
278 //
279 // Special initialization for PPB including making the PPB quiet
280 //
281 if ((PciIoDevice != NULL) && gFullEnumeration) {
282 InitializePpb (PciIoDevice);
283 }
284 }
285
286 if (PciIoDevice == NULL) {
287 return EFI_OUT_OF_RESOURCES;
288 }
289
290 //
291 // Update the bar information for this PCI device so as to support some specific device
292 //
293 UpdatePciInfo (PciIoDevice, &IgnoreOptionRom);
294
295 if (PciIoDevice->DevicePath == NULL) {
296 return EFI_OUT_OF_RESOURCES;
297 }
298
299 //
300 // Detect this function has option rom
301 //
302 if (gFullEnumeration) {
303 if (!IS_CARDBUS_BRIDGE (Pci) && !IgnoreOptionRom) {
304 GetOpRomInfo (PciIoDevice);
305 }
306
307 ResetPowerManagementFeature (PciIoDevice);
308 }
309
310 //
311 // Insert it into a global tree for future reference
312 //
313 InsertPciDevice (Bridge, PciIoDevice);
314
315 //
316 // Determine PCI device attributes
317 //
318
319 if (PciDevice != NULL) {
320 *PciDevice = PciIoDevice;
321 }
322
323 return EFI_SUCCESS;
324 }
325
326 /**
327 Dump the PPB padding resource information.
328
329 @param PciIoDevice PCI IO instance.
330 @param ResourceType The desired resource type to dump.
331 PciBarTypeUnknown means to dump all types of resources.
332 **/
333 VOID
334 DumpPpbPaddingResource (
335 IN PCI_IO_DEVICE *PciIoDevice,
336 IN PCI_BAR_TYPE ResourceType
337 )
338 {
339 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
340 PCI_BAR_TYPE Type;
341
342 if (PciIoDevice->ResourcePaddingDescriptors == NULL) {
343 return;
344 }
345
346 if ((ResourceType == PciBarTypeIo16) || (ResourceType == PciBarTypeIo32)) {
347 ResourceType = PciBarTypeIo;
348 }
349
350 for (Descriptor = PciIoDevice->ResourcePaddingDescriptors; Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR; Descriptor++) {
351 Type = PciBarTypeUnknown;
352 if ((Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) && (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO)) {
353 Type = PciBarTypeIo;
354 } else if ((Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) && (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM)) {
355 if (Descriptor->AddrSpaceGranularity == 32) {
356 //
357 // prefetchable
358 //
359 if (Descriptor->SpecificFlag == EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) {
360 Type = PciBarTypePMem32;
361 }
362
363 //
364 // Non-prefetchable
365 //
366 if (Descriptor->SpecificFlag == 0) {
367 Type = PciBarTypeMem32;
368 }
369 }
370
371 if (Descriptor->AddrSpaceGranularity == 64) {
372 //
373 // prefetchable
374 //
375 if (Descriptor->SpecificFlag == EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) {
376 Type = PciBarTypePMem64;
377 }
378
379 //
380 // Non-prefetchable
381 //
382 if (Descriptor->SpecificFlag == 0) {
383 Type = PciBarTypeMem64;
384 }
385 }
386 }
387
388 if ((Type != PciBarTypeUnknown) && ((ResourceType == PciBarTypeUnknown) || (ResourceType == Type))) {
389 DEBUG ((
390 DEBUG_INFO,
391 " Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n",
392 mBarTypeStr[Type],
393 Descriptor->AddrRangeMax,
394 Descriptor->AddrLen
395 ));
396 }
397 }
398 }
399
400 /**
401 Dump the PCI BAR information.
402
403 @param PciIoDevice PCI IO instance.
404 **/
405 VOID
406 DumpPciBars (
407 IN PCI_IO_DEVICE *PciIoDevice
408 )
409 {
410 UINTN Index;
411
412 for (Index = 0; Index < PCI_MAX_BAR; Index++) {
413 if (PciIoDevice->PciBar[Index].BarType == PciBarTypeUnknown) {
414 continue;
415 }
416
417 DEBUG ((
418 DEBUG_INFO,
419 " BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
420 Index,
421 mBarTypeStr[MIN (PciIoDevice->PciBar[Index].BarType, PciBarTypeMaxType)],
422 PciIoDevice->PciBar[Index].Alignment,
423 PciIoDevice->PciBar[Index].Length,
424 PciIoDevice->PciBar[Index].Offset
425 ));
426 }
427
428 for (Index = 0; Index < PCI_MAX_BAR; Index++) {
429 if ((PciIoDevice->VfPciBar[Index].BarType == PciBarTypeUnknown) && (PciIoDevice->VfPciBar[Index].Length == 0)) {
430 continue;
431 }
432
433 DEBUG ((
434 DEBUG_INFO,
435 " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
436 Index,
437 mBarTypeStr[MIN (PciIoDevice->VfPciBar[Index].BarType, PciBarTypeMaxType)],
438 PciIoDevice->VfPciBar[Index].Alignment,
439 PciIoDevice->VfPciBar[Index].Length,
440 PciIoDevice->VfPciBar[Index].Offset
441 ));
442 }
443
444 DEBUG ((DEBUG_INFO, "\n"));
445 }
446
447 /**
448 Create PCI device instance for PCI device.
449
450 @param Bridge Parent bridge instance.
451 @param Pci Input PCI device information block.
452 @param Bus PCI device Bus NO.
453 @param Device PCI device Device NO.
454 @param Func PCI device's func NO.
455
456 @return Created PCI device instance.
457
458 **/
459 PCI_IO_DEVICE *
460 GatherDeviceInfo (
461 IN PCI_IO_DEVICE *Bridge,
462 IN PCI_TYPE00 *Pci,
463 IN UINT8 Bus,
464 IN UINT8 Device,
465 IN UINT8 Func
466 )
467 {
468 UINTN Offset;
469 UINTN BarIndex;
470 PCI_IO_DEVICE *PciIoDevice;
471
472 PciIoDevice = CreatePciIoDevice (
473 Bridge,
474 Pci,
475 Bus,
476 Device,
477 Func
478 );
479
480 if (PciIoDevice == NULL) {
481 return NULL;
482 }
483
484 //
485 // If it is a full enumeration, disconnect the device in advance
486 //
487 if (gFullEnumeration) {
488 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
489 }
490
491 //
492 // Start to parse the bars
493 //
494 for (Offset = 0x10, BarIndex = 0; Offset <= 0x24 && BarIndex < PCI_MAX_BAR; BarIndex++) {
495 Offset = PciParseBar (PciIoDevice, Offset, BarIndex);
496 }
497
498 //
499 // Parse the SR-IOV VF bars
500 //
501 if (PcdGetBool (PcdSrIovSupport) && (PciIoDevice->SrIovCapabilityOffset != 0)) {
502 for (Offset = PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0, BarIndex = 0;
503 Offset <= PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5;
504 BarIndex++)
505 {
506 ASSERT (BarIndex < PCI_MAX_BAR);
507 Offset = PciIovParseVfBar (PciIoDevice, Offset, BarIndex);
508 }
509 }
510
511 DEBUG_CODE (
512 DumpPciBars (PciIoDevice);
513 );
514 return PciIoDevice;
515 }
516
517 /**
518 Create PCI device instance for PCI-PCI bridge.
519
520 @param Bridge Parent bridge instance.
521 @param Pci Input PCI device information block.
522 @param Bus PCI device Bus NO.
523 @param Device PCI device Device NO.
524 @param Func PCI device's func NO.
525
526 @return Created PCI device instance.
527
528 **/
529 PCI_IO_DEVICE *
530 GatherPpbInfo (
531 IN PCI_IO_DEVICE *Bridge,
532 IN PCI_TYPE00 *Pci,
533 IN UINT8 Bus,
534 IN UINT8 Device,
535 IN UINT8 Func
536 )
537 {
538 PCI_IO_DEVICE *PciIoDevice;
539 EFI_STATUS Status;
540 UINT8 Value;
541 EFI_PCI_IO_PROTOCOL *PciIo;
542 UINT8 Temp;
543 UINT32 PMemBaseLimit;
544 UINT16 PrefetchableMemoryBase;
545 UINT16 PrefetchableMemoryLimit;
546
547 PciIoDevice = CreatePciIoDevice (
548 Bridge,
549 Pci,
550 Bus,
551 Device,
552 Func
553 );
554
555 if (PciIoDevice == NULL) {
556 return NULL;
557 }
558
559 if (gFullEnumeration) {
560 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
561
562 //
563 // Initialize the bridge control register
564 //
565 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);
566 }
567
568 //
569 // PPB can have two BARs
570 //
571 if (PciParseBar (PciIoDevice, 0x10, PPB_BAR_0) == 0x14) {
572 //
573 // Not 64-bit bar
574 //
575 PciParseBar (PciIoDevice, 0x14, PPB_BAR_1);
576 }
577
578 PciIo = &PciIoDevice->PciIo;
579
580 //
581 // Test whether it support 32 decode or not
582 //
583 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
584 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
585 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
586 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
587
588 if (Value != 0) {
589 if ((Value & 0x01) != 0) {
590 PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;
591 } else {
592 PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
593 }
594 }
595
596 //
597 // if PcdPciBridgeIoAlignmentProbe is TRUE, PCI bus driver probes
598 // PCI bridge supporting non-standard I/O window alignment less than 4K.
599 //
600
601 PciIoDevice->BridgeIoAlignment = 0xFFF;
602 if (FeaturePcdGet (PcdPciBridgeIoAlignmentProbe)) {
603 //
604 // Check any bits of bit 3-1 of I/O Base Register are writable.
605 // if so, it is assumed non-standard I/O window alignment is supported by this bridge.
606 // Per spec, bit 3-1 of I/O Base Register are reserved bits, so its content can't be assumed.
607 //
608 Value = (UINT8)(Temp ^ (BIT3 | BIT2 | BIT1));
609 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
610 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
611 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
612 Value = (UINT8)((Value ^ Temp) & (BIT3 | BIT2 | BIT1));
613 switch (Value) {
614 case BIT3:
615 PciIoDevice->BridgeIoAlignment = 0x7FF;
616 break;
617 case BIT3 | BIT2:
618 PciIoDevice->BridgeIoAlignment = 0x3FF;
619 break;
620 case BIT3 | BIT2 | BIT1:
621 PciIoDevice->BridgeIoAlignment = 0x1FF;
622 break;
623 }
624 }
625
626 Status = BarExisted (
627 PciIoDevice,
628 0x24,
629 NULL,
630 &PMemBaseLimit
631 );
632
633 //
634 // Test if it supports 64 memory or not
635 //
636 // The bottom 4 bits of both the Prefetchable Memory Base and Prefetchable Memory Limit
637 // registers:
638 // 0 - the bridge supports only 32 bit addresses.
639 // 1 - the bridge supports 64-bit addresses.
640 //
641 PrefetchableMemoryBase = (UINT16)(PMemBaseLimit & 0xffff);
642 PrefetchableMemoryLimit = (UINT16)(PMemBaseLimit >> 16);
643 if (!EFI_ERROR (Status) &&
644 ((PrefetchableMemoryBase & 0x000f) == 0x0001) &&
645 ((PrefetchableMemoryLimit & 0x000f) == 0x0001))
646 {
647 Status = BarExisted (
648 PciIoDevice,
649 0x28,
650 NULL,
651 NULL
652 );
653
654 if (!EFI_ERROR (Status)) {
655 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
656 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
657 } else {
658 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
659 }
660 }
661
662 //
663 // Memory 32 code is required for ppb
664 //
665 PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
666
667 GetResourcePaddingPpb (PciIoDevice);
668
669 DEBUG_CODE (
670 DumpPpbPaddingResource (PciIoDevice, PciBarTypeUnknown);
671 DumpPciBars (PciIoDevice);
672 );
673
674 return PciIoDevice;
675 }
676
677 /**
678 Create PCI device instance for PCI Card bridge device.
679
680 @param Bridge Parent bridge instance.
681 @param Pci Input PCI device information block.
682 @param Bus PCI device Bus NO.
683 @param Device PCI device Device NO.
684 @param Func PCI device's func NO.
685
686 @return Created PCI device instance.
687
688 **/
689 PCI_IO_DEVICE *
690 GatherP2CInfo (
691 IN PCI_IO_DEVICE *Bridge,
692 IN PCI_TYPE00 *Pci,
693 IN UINT8 Bus,
694 IN UINT8 Device,
695 IN UINT8 Func
696 )
697 {
698 PCI_IO_DEVICE *PciIoDevice;
699
700 PciIoDevice = CreatePciIoDevice (
701 Bridge,
702 Pci,
703 Bus,
704 Device,
705 Func
706 );
707
708 if (PciIoDevice == NULL) {
709 return NULL;
710 }
711
712 if (gFullEnumeration) {
713 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
714
715 //
716 // Initialize the bridge control register
717 //
718 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);
719 }
720
721 //
722 // P2C only has one bar that is in 0x10
723 //
724 PciParseBar (PciIoDevice, 0x10, P2C_BAR_0);
725
726 //
727 // Read PciBar information from the bar register
728 //
729 GetBackPcCardBar (PciIoDevice);
730 PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED |
731 EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |
732 EFI_BRIDGE_IO32_DECODE_SUPPORTED;
733
734 DEBUG_CODE (
735 DumpPciBars (PciIoDevice);
736 );
737
738 return PciIoDevice;
739 }
740
741 /**
742 Create device path for pci device.
743
744 @param ParentDevicePath Parent bridge's path.
745 @param PciIoDevice Pci device instance.
746
747 @return Device path protocol instance for specific pci device.
748
749 **/
750 EFI_DEVICE_PATH_PROTOCOL *
751 CreatePciDevicePath (
752 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
753 IN PCI_IO_DEVICE *PciIoDevice
754 )
755 {
756 PCI_DEVICE_PATH PciNode;
757
758 //
759 // Create PCI device path
760 //
761 PciNode.Header.Type = HARDWARE_DEVICE_PATH;
762 PciNode.Header.SubType = HW_PCI_DP;
763 SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
764
765 PciNode.Device = PciIoDevice->DeviceNumber;
766 PciNode.Function = PciIoDevice->FunctionNumber;
767 PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);
768
769 return PciIoDevice->DevicePath;
770 }
771
772 /**
773 Check whether the PCI IOV VF bar is existed or not.
774
775 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
776 @param Offset The offset.
777 @param BarLengthValue The bar length value returned.
778 @param OriginalBarValue The original bar value returned.
779
780 @retval EFI_NOT_FOUND The bar doesn't exist.
781 @retval EFI_SUCCESS The bar exist.
782
783 **/
784 EFI_STATUS
785 VfBarExisted (
786 IN PCI_IO_DEVICE *PciIoDevice,
787 IN UINTN Offset,
788 OUT UINT32 *BarLengthValue,
789 OUT UINT32 *OriginalBarValue
790 )
791 {
792 EFI_PCI_IO_PROTOCOL *PciIo;
793 UINT32 OriginalValue;
794 UINT32 Value;
795 EFI_TPL OldTpl;
796
797 //
798 // Ensure it is called properly
799 //
800 ASSERT (PciIoDevice->SrIovCapabilityOffset != 0);
801 if (PciIoDevice->SrIovCapabilityOffset == 0) {
802 return EFI_NOT_FOUND;
803 }
804
805 PciIo = &PciIoDevice->PciIo;
806
807 //
808 // Preserve the original value
809 //
810
811 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &OriginalValue);
812
813 //
814 // Raise TPL to high level to disable timer interrupt while the BAR is probed
815 //
816 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
817
818 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &gAllOne);
819 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &Value);
820
821 //
822 // Write back the original value
823 //
824 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &OriginalValue);
825
826 //
827 // Restore TPL to its original level
828 //
829 gBS->RestoreTPL (OldTpl);
830
831 if (BarLengthValue != NULL) {
832 *BarLengthValue = Value;
833 }
834
835 if (OriginalBarValue != NULL) {
836 *OriginalBarValue = OriginalValue;
837 }
838
839 if (Value == 0) {
840 return EFI_NOT_FOUND;
841 } else {
842 return EFI_SUCCESS;
843 }
844 }
845
846 /**
847 Check whether the bar is existed or not.
848
849 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
850 @param Offset The offset.
851 @param BarLengthValue The bar length value returned.
852 @param OriginalBarValue The original bar value returned.
853
854 @retval EFI_NOT_FOUND The bar doesn't exist.
855 @retval EFI_SUCCESS The bar exist.
856
857 **/
858 EFI_STATUS
859 BarExisted (
860 IN PCI_IO_DEVICE *PciIoDevice,
861 IN UINTN Offset,
862 OUT UINT32 *BarLengthValue,
863 OUT UINT32 *OriginalBarValue
864 )
865 {
866 EFI_PCI_IO_PROTOCOL *PciIo;
867 UINT32 OriginalValue;
868 UINT32 Value;
869 EFI_TPL OldTpl;
870
871 PciIo = &PciIoDevice->PciIo;
872
873 //
874 // Preserve the original value
875 //
876 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8)Offset, 1, &OriginalValue);
877
878 //
879 // Raise TPL to high level to disable timer interrupt while the BAR is probed
880 //
881 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
882
883 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8)Offset, 1, &gAllOne);
884 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8)Offset, 1, &Value);
885
886 //
887 // Write back the original value
888 //
889 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8)Offset, 1, &OriginalValue);
890
891 //
892 // Restore TPL to its original level
893 //
894 gBS->RestoreTPL (OldTpl);
895
896 if (BarLengthValue != NULL) {
897 *BarLengthValue = Value;
898 }
899
900 if (OriginalBarValue != NULL) {
901 *OriginalBarValue = OriginalValue;
902 }
903
904 if (Value == 0) {
905 return EFI_NOT_FOUND;
906 } else {
907 return EFI_SUCCESS;
908 }
909 }
910
911 /**
912 Test whether the device can support given attributes.
913
914 @param PciIoDevice Pci device instance.
915 @param Command Input command register value, and
916 returned supported register value.
917 @param BridgeControl Input bridge control value for PPB or P2C, and
918 returned supported bridge control value.
919 @param OldCommand Returned and stored old command register offset.
920 @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C.
921
922 **/
923 VOID
924 PciTestSupportedAttribute (
925 IN PCI_IO_DEVICE *PciIoDevice,
926 IN OUT UINT16 *Command,
927 IN OUT UINT16 *BridgeControl,
928 OUT UINT16 *OldCommand,
929 OUT UINT16 *OldBridgeControl
930 )
931 {
932 EFI_TPL OldTpl;
933 UINT16 CommandValue;
934
935 //
936 // Preserve the original value
937 //
938 PCI_READ_COMMAND_REGISTER (PciIoDevice, OldCommand);
939
940 //
941 // Raise TPL to high level to disable timer interrupt while the BAR is probed
942 //
943 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
944 CommandValue = *Command | *OldCommand;
945
946 PCI_SET_COMMAND_REGISTER (PciIoDevice, CommandValue);
947 PCI_READ_COMMAND_REGISTER (PciIoDevice, &CommandValue);
948
949 *Command = *Command & CommandValue;
950 //
951 // Write back the original value
952 //
953 PCI_SET_COMMAND_REGISTER (PciIoDevice, *OldCommand);
954
955 //
956 // Restore TPL to its original level
957 //
958 gBS->RestoreTPL (OldTpl);
959
960 if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
961 //
962 // Preserve the original value
963 //
964 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, OldBridgeControl);
965
966 //
967 // Raise TPL to high level to disable timer interrupt while the BAR is probed
968 //
969 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
970
971 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *BridgeControl);
972 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);
973
974 //
975 // Write back the original value
976 //
977 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *OldBridgeControl);
978
979 //
980 // Restore TPL to its original level
981 //
982 gBS->RestoreTPL (OldTpl);
983 } else {
984 *OldBridgeControl = 0;
985 *BridgeControl = 0;
986 }
987 }
988
989 /**
990 Set the supported or current attributes of a PCI device.
991
992 @param PciIoDevice Structure pointer for PCI device.
993 @param Command Command register value.
994 @param BridgeControl Bridge control value for PPB or P2C.
995 @param Option Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.
996
997 **/
998 VOID
999 PciSetDeviceAttribute (
1000 IN PCI_IO_DEVICE *PciIoDevice,
1001 IN UINT16 Command,
1002 IN UINT16 BridgeControl,
1003 IN UINTN Option
1004 )
1005 {
1006 UINT64 Attributes;
1007
1008 Attributes = 0;
1009
1010 if ((Command & EFI_PCI_COMMAND_IO_SPACE) != 0) {
1011 Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;
1012 }
1013
1014 if ((Command & EFI_PCI_COMMAND_MEMORY_SPACE) != 0) {
1015 Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;
1016 }
1017
1018 if ((Command & EFI_PCI_COMMAND_BUS_MASTER) != 0) {
1019 Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
1020 }
1021
1022 if ((Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {
1023 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
1024 }
1025
1026 if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) != 0) {
1027 Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
1028 }
1029
1030 if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) != 0) {
1031 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
1032 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
1033 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
1034 }
1035
1036 if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16) != 0) {
1037 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16;
1038 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16;
1039 }
1040
1041 if (Option == EFI_SET_SUPPORTS) {
1042 Attributes |= (UINT64)(EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE |
1043 EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED |
1044 EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE |
1045 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |
1046 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM |
1047 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE);
1048
1049 if (IS_PCI_LPC (&PciIoDevice->Pci)) {
1050 Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;
1051 Attributes |= (mReserveIsaAliases ? (UINT64)EFI_PCI_IO_ATTRIBUTE_ISA_IO : \
1052 (UINT64)EFI_PCI_IO_ATTRIBUTE_ISA_IO_16);
1053 }
1054
1055 if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
1056 //
1057 // For bridge, it should support IDE attributes
1058 //
1059 Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;
1060 Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;
1061
1062 if (mReserveVgaAliases) {
1063 Attributes &= ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 | \
1064 EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16);
1065 } else {
1066 Attributes &= ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO | \
1067 EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);
1068 }
1069 } else {
1070 if (IS_PCI_IDE (&PciIoDevice->Pci)) {
1071 Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;
1072 Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;
1073 }
1074
1075 if (IS_PCI_VGA (&PciIoDevice->Pci)) {
1076 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
1077 Attributes |= (mReserveVgaAliases ? (UINT64)EFI_PCI_IO_ATTRIBUTE_VGA_IO : \
1078 (UINT64)EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);
1079 }
1080 }
1081
1082 PciIoDevice->Supports = Attributes;
1083 PciIoDevice->Supports &= ((PciIoDevice->Parent->Supports) | \
1084 EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | \
1085 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER);
1086 } else {
1087 //
1088 // When this attribute is clear, the RomImage and RomSize fields in the PCI IO were
1089 // initialized based on the PCI option ROM found through the ROM BAR of the PCI controller.
1090 // When this attribute is set, the PCI option ROM described by the RomImage and RomSize
1091 // fields is not from the the ROM BAR of the PCI controller.
1092 //
1093 if (!PciIoDevice->EmbeddedRom) {
1094 Attributes |= EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM;
1095 }
1096
1097 PciIoDevice->Attributes = Attributes;
1098 }
1099 }
1100
1101 /**
1102 Determine if the device can support Fast Back to Back attribute.
1103
1104 @param PciIoDevice Pci device instance.
1105 @param StatusIndex Status register value.
1106
1107 @retval EFI_SUCCESS This device support Fast Back to Back attribute.
1108 @retval EFI_UNSUPPORTED This device doesn't support Fast Back to Back attribute.
1109
1110 **/
1111 EFI_STATUS
1112 GetFastBackToBackSupport (
1113 IN PCI_IO_DEVICE *PciIoDevice,
1114 IN UINT8 StatusIndex
1115 )
1116 {
1117 EFI_PCI_IO_PROTOCOL *PciIo;
1118 EFI_STATUS Status;
1119 UINT32 StatusRegister;
1120
1121 //
1122 // Read the status register
1123 //
1124 PciIo = &PciIoDevice->PciIo;
1125 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, StatusIndex, 1, &StatusRegister);
1126 if (EFI_ERROR (Status)) {
1127 return EFI_UNSUPPORTED;
1128 }
1129
1130 //
1131 // Check the Fast B2B bit
1132 //
1133 if ((StatusRegister & EFI_PCI_FAST_BACK_TO_BACK_CAPABLE) != 0) {
1134 return EFI_SUCCESS;
1135 } else {
1136 return EFI_UNSUPPORTED;
1137 }
1138 }
1139
1140 /**
1141 Process the option ROM for all the children of the specified parent PCI device.
1142 It can only be used after the first full Option ROM process.
1143
1144 @param PciIoDevice Pci device instance.
1145
1146 **/
1147 VOID
1148 ProcessOptionRomLight (
1149 IN PCI_IO_DEVICE *PciIoDevice
1150 )
1151 {
1152 PCI_IO_DEVICE *Temp;
1153 LIST_ENTRY *CurrentLink;
1154
1155 //
1156 // For RootBridge, PPB , P2C, go recursively to traverse all its children
1157 //
1158 CurrentLink = PciIoDevice->ChildList.ForwardLink;
1159 while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
1160 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
1161
1162 if (!IsListEmpty (&Temp->ChildList)) {
1163 ProcessOptionRomLight (Temp);
1164 }
1165
1166 Temp->AllOpRomProcessed = PciRomGetImageMapping (Temp);
1167
1168 CurrentLink = CurrentLink->ForwardLink;
1169 }
1170 }
1171
1172 /**
1173 Determine the related attributes of all devices under a Root Bridge.
1174
1175 @param PciIoDevice PCI device instance.
1176
1177 **/
1178 EFI_STATUS
1179 DetermineDeviceAttribute (
1180 IN PCI_IO_DEVICE *PciIoDevice
1181 )
1182 {
1183 UINT16 Command;
1184 UINT16 BridgeControl;
1185 UINT16 OldCommand;
1186 UINT16 OldBridgeControl;
1187 BOOLEAN FastB2BSupport;
1188 PCI_IO_DEVICE *Temp;
1189 LIST_ENTRY *CurrentLink;
1190 EFI_STATUS Status;
1191
1192 //
1193 // For Root Bridge, just copy it by RootBridgeIo protocol
1194 // so as to keep consistent with the actual attribute
1195 //
1196 if (PciIoDevice->Parent == NULL) {
1197 Status = PciIoDevice->PciRootBridgeIo->GetAttributes (
1198 PciIoDevice->PciRootBridgeIo,
1199 &PciIoDevice->Supports,
1200 &PciIoDevice->Attributes
1201 );
1202 if (EFI_ERROR (Status)) {
1203 return Status;
1204 }
1205
1206 //
1207 // Assume the PCI Root Bridge supports DAC
1208 //
1209 PciIoDevice->Supports |= (UINT64)(EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |
1210 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM |
1211 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE);
1212 } else {
1213 //
1214 // Set the attributes to be checked for common PCI devices and PPB or P2C
1215 // Since some devices only support part of them, it is better to set the
1216 // attribute according to its command or bridge control register
1217 //
1218 Command = EFI_PCI_COMMAND_IO_SPACE |
1219 EFI_PCI_COMMAND_MEMORY_SPACE |
1220 EFI_PCI_COMMAND_BUS_MASTER |
1221 EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
1222
1223 BridgeControl = EFI_PCI_BRIDGE_CONTROL_ISA | EFI_PCI_BRIDGE_CONTROL_VGA | EFI_PCI_BRIDGE_CONTROL_VGA_16;
1224
1225 //
1226 // Test whether the device can support attributes above
1227 //
1228 PciTestSupportedAttribute (PciIoDevice, &Command, &BridgeControl, &OldCommand, &OldBridgeControl);
1229
1230 //
1231 // Set the supported attributes for specified PCI device
1232 //
1233 PciSetDeviceAttribute (PciIoDevice, Command, BridgeControl, EFI_SET_SUPPORTS);
1234
1235 //
1236 // Set the current attributes for specified PCI device
1237 //
1238 PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES);
1239
1240 //
1241 // Enable other PCI supported attributes but not defined in PCI_IO_PROTOCOL
1242 // For PCI Express devices, Memory Write and Invalidate is hardwired to 0b so only enable it for PCI devices.
1243 if (!PciIoDevice->IsPciExp) {
1244 PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);
1245 }
1246 }
1247
1248 FastB2BSupport = TRUE;
1249
1250 //
1251 // P2C can not support FB2B on the secondary side
1252 //
1253 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
1254 FastB2BSupport = FALSE;
1255 }
1256
1257 //
1258 // For RootBridge, PPB , P2C, go recursively to traverse all its children
1259 //
1260 CurrentLink = PciIoDevice->ChildList.ForwardLink;
1261 while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
1262 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
1263 Status = DetermineDeviceAttribute (Temp);
1264 if (EFI_ERROR (Status)) {
1265 return Status;
1266 }
1267
1268 //
1269 // Detect Fast Back to Back support for the device under the bridge
1270 //
1271 Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET);
1272 if (FastB2BSupport && EFI_ERROR (Status)) {
1273 FastB2BSupport = FALSE;
1274 }
1275
1276 CurrentLink = CurrentLink->ForwardLink;
1277 }
1278
1279 //
1280 // Set or clear Fast Back to Back bit for the whole bridge
1281 //
1282 if (!IsListEmpty (&PciIoDevice->ChildList)) {
1283 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
1284 Status = GetFastBackToBackSupport (PciIoDevice, PCI_BRIDGE_STATUS_REGISTER_OFFSET);
1285
1286 if (EFI_ERROR (Status) || (!FastB2BSupport)) {
1287 FastB2BSupport = FALSE;
1288 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);
1289 } else {
1290 PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);
1291 }
1292 }
1293
1294 CurrentLink = PciIoDevice->ChildList.ForwardLink;
1295 while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
1296 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
1297 if (FastB2BSupport) {
1298 PCI_ENABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);
1299 } else {
1300 PCI_DISABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);
1301 }
1302
1303 CurrentLink = CurrentLink->ForwardLink;
1304 }
1305 }
1306
1307 //
1308 // End for IsListEmpty
1309 //
1310 return EFI_SUCCESS;
1311 }
1312
1313 /**
1314 This routine is used to update the bar information for those incompatible PCI device.
1315
1316 @param PciIoDevice Input Pci device instance. Output Pci device instance with updated
1317 Bar information.
1318 @param IgnoreOptionRom Output If the option rom of incompatible device need to be ignored.
1319
1320 @retval EFI_SUCCESS Successfully updated bar information.
1321 @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list.
1322
1323 **/
1324 EFI_STATUS
1325 UpdatePciInfo (
1326 IN OUT PCI_IO_DEVICE *PciIoDevice,
1327 OUT BOOLEAN *IgnoreOptionRom
1328 )
1329 {
1330 EFI_STATUS Status;
1331 UINTN BarIndex;
1332 BOOLEAN SetFlag;
1333 VOID *Configuration;
1334 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
1335
1336 Configuration = NULL;
1337 Status = EFI_SUCCESS;
1338
1339 if (gIncompatiblePciDeviceSupport == NULL) {
1340 //
1341 // It can only be supported after the Incompatible PCI Device
1342 // Support Protocol has been installed
1343 //
1344 Status = gBS->LocateProtocol (
1345 &gEfiIncompatiblePciDeviceSupportProtocolGuid,
1346 NULL,
1347 (VOID **)&gIncompatiblePciDeviceSupport
1348 );
1349 }
1350
1351 if (Status == EFI_SUCCESS) {
1352 //
1353 // Check whether the device belongs to incompatible devices from protocol or not
1354 // If it is , then get its special requirement in the ACPI table
1355 //
1356 Status = gIncompatiblePciDeviceSupport->CheckDevice (
1357 gIncompatiblePciDeviceSupport,
1358 PciIoDevice->Pci.Hdr.VendorId,
1359 PciIoDevice->Pci.Hdr.DeviceId,
1360 PciIoDevice->Pci.Hdr.RevisionID,
1361 PciIoDevice->Pci.Device.SubsystemVendorID,
1362 PciIoDevice->Pci.Device.SubsystemID,
1363 &Configuration
1364 );
1365 }
1366
1367 if (EFI_ERROR (Status) || (Configuration == NULL)) {
1368 return EFI_UNSUPPORTED;
1369 }
1370
1371 //
1372 // Update PCI device information from the ACPI table
1373 //
1374 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Configuration;
1375
1376 while (Ptr->Desc != ACPI_END_TAG_DESCRIPTOR) {
1377 if (Ptr->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
1378 //
1379 // The format is not support
1380 //
1381 break;
1382 }
1383
1384 //
1385 // According to "Table 20. ACPI 2.0 & 3.0 QWORD Address Space Descriptor Usage"
1386 // in PI Spec 1.7, Type-specific flags can be set to 0 when Address Translation
1387 // Offset == 6 to skip device option ROM (do not probe option rom BAR).
1388 //
1389 if (((Ptr->AddrTranslationOffset == PCI_MAX_BAR) && (Ptr->SpecificFlag == 0))) {
1390 *IgnoreOptionRom = TRUE;
1391 Ptr++;
1392 continue;
1393 }
1394
1395 for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) {
1396 if ((Ptr->AddrTranslationOffset != MAX_UINT64) &&
1397 (Ptr->AddrTranslationOffset != MAX_UINT8) &&
1398 (Ptr->AddrTranslationOffset != BarIndex)
1399 )
1400 {
1401 //
1402 // Skip updating when AddrTranslationOffset is not MAX_UINT64 or MAX_UINT8 (wide match).
1403 // Skip updating when current BarIndex doesn't equal to AddrTranslationOffset.
1404 // Comparing against MAX_UINT8 is to keep backward compatibility.
1405 //
1406 continue;
1407 }
1408
1409 SetFlag = FALSE;
1410 switch (Ptr->ResType) {
1411 case ACPI_ADDRESS_SPACE_TYPE_MEM:
1412
1413 //
1414 // Make sure the bar is memory type
1415 //
1416 if (CheckBarType (PciIoDevice, (UINT8)BarIndex, PciBarTypeMem)) {
1417 SetFlag = TRUE;
1418
1419 //
1420 // Ignored if granularity is 0.
1421 // Ignored if PCI BAR is I/O or 32-bit memory.
1422 // If PCI BAR is 64-bit memory and granularity is 32, then
1423 // the PCI BAR resource is allocated below 4GB.
1424 // If PCI BAR is 64-bit memory and granularity is 64, then
1425 // the PCI BAR resource is allocated above 4GB.
1426 //
1427 if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeMem64) {
1428 switch (Ptr->AddrSpaceGranularity) {
1429 case 32:
1430 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
1431 case 64:
1432 PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE;
1433 break;
1434 default:
1435 break;
1436 }
1437 }
1438
1439 if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypePMem64) {
1440 switch (Ptr->AddrSpaceGranularity) {
1441 case 32:
1442 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
1443 case 64:
1444 PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE;
1445 break;
1446 default:
1447 break;
1448 }
1449 }
1450 }
1451
1452 break;
1453
1454 case ACPI_ADDRESS_SPACE_TYPE_IO:
1455
1456 //
1457 // Make sure the bar is IO type
1458 //
1459 if (CheckBarType (PciIoDevice, (UINT8)BarIndex, PciBarTypeIo)) {
1460 SetFlag = TRUE;
1461 }
1462
1463 break;
1464 }
1465
1466 if (SetFlag) {
1467 //
1468 // Update the new alignment for the device
1469 //
1470 SetNewAlign (&(PciIoDevice->PciBar[BarIndex].Alignment), Ptr->AddrRangeMax);
1471
1472 //
1473 // Update the new length for the device
1474 //
1475 if (Ptr->AddrLen != 0) {
1476 PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen;
1477 }
1478 }
1479 }
1480
1481 Ptr++;
1482 }
1483
1484 FreePool (Configuration);
1485
1486 return EFI_SUCCESS;
1487 }
1488
1489 /**
1490 This routine will update the alignment with the new alignment.
1491 Compare with OLD_ALIGN/EVEN_ALIGN/SQUAD_ALIGN/DQUAD_ALIGN is to keep
1492 backward compatibility.
1493
1494 @param Alignment Input Old alignment. Output updated alignment.
1495 @param NewAlignment New alignment.
1496
1497 **/
1498 VOID
1499 SetNewAlign (
1500 IN OUT UINT64 *Alignment,
1501 IN UINT64 NewAlignment
1502 )
1503 {
1504 UINT64 OldAlignment;
1505 UINTN ShiftBit;
1506
1507 //
1508 // The new alignment is the same as the original,
1509 // so skip it
1510 //
1511 if ((NewAlignment == 0) || (NewAlignment == OLD_ALIGN)) {
1512 return;
1513 }
1514
1515 //
1516 // Check the validity of the parameter
1517 //
1518 if ((NewAlignment != EVEN_ALIGN) &&
1519 (NewAlignment != SQUAD_ALIGN) &&
1520 (NewAlignment != DQUAD_ALIGN))
1521 {
1522 *Alignment = NewAlignment;
1523 return;
1524 }
1525
1526 OldAlignment = (*Alignment) + 1;
1527 ShiftBit = 0;
1528
1529 //
1530 // Get the first non-zero hex value of the length
1531 //
1532 while ((OldAlignment & 0x0F) == 0x00) {
1533 OldAlignment = RShiftU64 (OldAlignment, 4);
1534 ShiftBit += 4;
1535 }
1536
1537 //
1538 // Adjust the alignment to even, quad or double quad boundary
1539 //
1540 if (NewAlignment == EVEN_ALIGN) {
1541 if ((OldAlignment & 0x01) != 0) {
1542 OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01);
1543 }
1544 } else if (NewAlignment == SQUAD_ALIGN) {
1545 if ((OldAlignment & 0x03) != 0) {
1546 OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03);
1547 }
1548 } else if (NewAlignment == DQUAD_ALIGN) {
1549 if ((OldAlignment & 0x07) != 0) {
1550 OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07);
1551 }
1552 }
1553
1554 //
1555 // Update the old value
1556 //
1557 NewAlignment = LShiftU64 (OldAlignment, ShiftBit) - 1;
1558 *Alignment = NewAlignment;
1559
1560 return;
1561 }
1562
1563 /**
1564 Parse PCI IOV VF bar information and fill them into PCI device instance.
1565
1566 @param PciIoDevice Pci device instance.
1567 @param Offset Bar offset.
1568 @param BarIndex Bar index.
1569
1570 @return Next bar offset.
1571
1572 **/
1573 UINTN
1574 PciIovParseVfBar (
1575 IN PCI_IO_DEVICE *PciIoDevice,
1576 IN UINTN Offset,
1577 IN UINTN BarIndex
1578 )
1579 {
1580 UINT32 Value;
1581 UINT32 OriginalValue;
1582 UINT32 Mask;
1583 EFI_STATUS Status;
1584
1585 //
1586 // Ensure it is called properly
1587 //
1588 ASSERT (PciIoDevice->SrIovCapabilityOffset != 0);
1589 if (PciIoDevice->SrIovCapabilityOffset == 0) {
1590 return 0;
1591 }
1592
1593 OriginalValue = 0;
1594 Value = 0;
1595
1596 Status = VfBarExisted (
1597 PciIoDevice,
1598 Offset,
1599 &Value,
1600 &OriginalValue
1601 );
1602
1603 if (EFI_ERROR (Status)) {
1604 PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;
1605 PciIoDevice->VfPciBar[BarIndex].Length = 0;
1606 PciIoDevice->VfPciBar[BarIndex].Alignment = 0;
1607
1608 //
1609 // Scan all the BARs anyway
1610 //
1611 PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16)Offset;
1612 return Offset + 4;
1613 }
1614
1615 PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16)Offset;
1616 if ((Value & 0x01) != 0) {
1617 //
1618 // Device I/Os. Impossible
1619 //
1620 ASSERT (FALSE);
1621 return Offset + 4;
1622 } else {
1623 Mask = 0xfffffff0;
1624
1625 PciIoDevice->VfPciBar[BarIndex].BaseAddress = OriginalValue & Mask;
1626
1627 switch (Value & 0x07) {
1628 //
1629 // memory space; anywhere in 32 bit address space
1630 //
1631 case 0x00:
1632 if ((Value & 0x08) != 0) {
1633 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem32;
1634 } else {
1635 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem32;
1636 }
1637
1638 PciIoDevice->VfPciBar[BarIndex].Length = (~(Value & Mask)) + 1;
1639 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
1640
1641 //
1642 // Adjust Length
1643 //
1644 PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs);
1645 //
1646 // Adjust Alignment
1647 //
1648 if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
1649 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
1650 }
1651
1652 break;
1653
1654 //
1655 // memory space; anywhere in 64 bit address space
1656 //
1657 case 0x04:
1658 if ((Value & 0x08) != 0) {
1659 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem64;
1660 } else {
1661 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem64;
1662 }
1663
1664 //
1665 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1666 // is regarded as an extension for the first bar. As a result
1667 // the sizing will be conducted on combined 64 bit value
1668 // Here just store the masked first 32bit value for future size
1669 // calculation
1670 //
1671 PciIoDevice->VfPciBar[BarIndex].Length = Value & Mask;
1672 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
1673
1674 if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
1675 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
1676 }
1677
1678 //
1679 // Increment the offset to point to next DWORD
1680 //
1681 Offset += 4;
1682
1683 Status = VfBarExisted (
1684 PciIoDevice,
1685 Offset,
1686 &Value,
1687 &OriginalValue
1688 );
1689
1690 if (EFI_ERROR (Status)) {
1691 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeUnknown;
1692 return Offset + 4;
1693 }
1694
1695 //
1696 // Fix the length to support some special 64 bit BAR
1697 //
1698 Value |= ((UINT32)-1 << HighBitSet32 (Value));
1699
1700 //
1701 // Calculate the size of 64bit bar
1702 //
1703 PciIoDevice->VfPciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64)OriginalValue, 32);
1704
1705 PciIoDevice->VfPciBar[BarIndex].Length = PciIoDevice->VfPciBar[BarIndex].Length | LShiftU64 ((UINT64)Value, 32);
1706 PciIoDevice->VfPciBar[BarIndex].Length = (~(PciIoDevice->VfPciBar[BarIndex].Length)) + 1;
1707 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
1708
1709 //
1710 // Adjust Length
1711 //
1712 PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs);
1713 //
1714 // Adjust Alignment
1715 //
1716 if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
1717 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
1718 }
1719
1720 break;
1721
1722 //
1723 // reserved
1724 //
1725 default:
1726 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeUnknown;
1727 PciIoDevice->VfPciBar[BarIndex].Length = (~(Value & Mask)) + 1;
1728 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
1729
1730 if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
1731 PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
1732 }
1733
1734 break;
1735 }
1736 }
1737
1738 //
1739 // Check the length again so as to keep compatible with some special bars
1740 //
1741 if (PciIoDevice->VfPciBar[BarIndex].Length == 0) {
1742 PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeUnknown;
1743 PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;
1744 PciIoDevice->VfPciBar[BarIndex].Alignment = 0;
1745 }
1746
1747 //
1748 // Increment number of bar
1749 //
1750 return Offset + 4;
1751 }
1752
1753 /**
1754 Parse PCI bar information and fill them into PCI device instance.
1755
1756 @param PciIoDevice Pci device instance.
1757 @param Offset Bar offset.
1758 @param BarIndex Bar index.
1759
1760 @return Next bar offset.
1761
1762 **/
1763 UINTN
1764 PciParseBar (
1765 IN PCI_IO_DEVICE *PciIoDevice,
1766 IN UINTN Offset,
1767 IN UINTN BarIndex
1768 )
1769 {
1770 UINT32 Value;
1771 UINT32 OriginalValue;
1772 UINT32 Mask;
1773 EFI_STATUS Status;
1774
1775 OriginalValue = 0;
1776 Value = 0;
1777
1778 Status = BarExisted (
1779 PciIoDevice,
1780 Offset,
1781 &Value,
1782 &OriginalValue
1783 );
1784
1785 if (EFI_ERROR (Status)) {
1786 PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
1787 PciIoDevice->PciBar[BarIndex].Length = 0;
1788 PciIoDevice->PciBar[BarIndex].Alignment = 0;
1789
1790 //
1791 // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
1792 //
1793 PciIoDevice->PciBar[BarIndex].Offset = (UINT8)Offset;
1794 return Offset + 4;
1795 }
1796
1797 PciIoDevice->PciBar[BarIndex].BarTypeFixed = FALSE;
1798 PciIoDevice->PciBar[BarIndex].Offset = (UINT8)Offset;
1799 if ((Value & 0x01) != 0) {
1800 //
1801 // Device I/Os
1802 //
1803 Mask = 0xfffffffc;
1804
1805 if ((Value & 0xFFFF0000) != 0) {
1806 //
1807 // It is a IO32 bar
1808 //
1809 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo32;
1810 PciIoDevice->PciBar[BarIndex].Length = ((~(Value & Mask)) + 1);
1811 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1812 } else {
1813 //
1814 // It is a IO16 bar
1815 //
1816 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo16;
1817 PciIoDevice->PciBar[BarIndex].Length = 0x0000FFFF & ((~(Value & Mask)) + 1);
1818 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1819 }
1820
1821 //
1822 // Workaround. Some platforms implement IO bar with 0 length
1823 // Need to treat it as no-bar
1824 //
1825 if (PciIoDevice->PciBar[BarIndex].Length == 0) {
1826 PciIoDevice->PciBar[BarIndex].BarType = (PCI_BAR_TYPE)0;
1827 }
1828
1829 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
1830 } else {
1831 Mask = 0xfffffff0;
1832
1833 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
1834
1835 switch (Value & 0x07) {
1836 //
1837 // memory space; anywhere in 32 bit address space
1838 //
1839 case 0x00:
1840 if ((Value & 0x08) != 0) {
1841 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
1842 } else {
1843 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
1844 }
1845
1846 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
1847 if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {
1848 //
1849 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1850 //
1851 PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);
1852 } else {
1853 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1854 }
1855
1856 break;
1857
1858 //
1859 // memory space; anywhere in 64 bit address space
1860 //
1861 case 0x04:
1862 if ((Value & 0x08) != 0) {
1863 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;
1864 } else {
1865 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;
1866 }
1867
1868 //
1869 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1870 // is regarded as an extension for the first bar. As a result
1871 // the sizing will be conducted on combined 64 bit value
1872 // Here just store the masked first 32bit value for future size
1873 // calculation
1874 //
1875 PciIoDevice->PciBar[BarIndex].Length = Value & Mask;
1876 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1877
1878 //
1879 // Increment the offset to point to next DWORD
1880 //
1881 Offset += 4;
1882
1883 Status = BarExisted (
1884 PciIoDevice,
1885 Offset,
1886 &Value,
1887 &OriginalValue
1888 );
1889
1890 if (EFI_ERROR (Status)) {
1891 //
1892 // the high 32 bit does not claim any BAR, we need to re-check the low 32 bit BAR again
1893 //
1894 if (PciIoDevice->PciBar[BarIndex].Length == 0) {
1895 //
1896 // some device implement MMIO bar with 0 length, need to treat it as no-bar
1897 //
1898 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
1899 return Offset + 4;
1900 }
1901 }
1902
1903 //
1904 // Fix the length to support some special 64 bit BAR
1905 //
1906 if (Value == 0) {
1907 DEBUG ((DEBUG_INFO, "[PciBus]BAR probing for upper 32bit of MEM64 BAR returns 0, change to 0xFFFFFFFF.\n"));
1908 Value = (UINT32)-1;
1909 } else {
1910 Value |= ((UINT32)(-1) << HighBitSet32 (Value));
1911 }
1912
1913 //
1914 // Calculate the size of 64bit bar
1915 //
1916 PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64)OriginalValue, 32);
1917
1918 PciIoDevice->PciBar[BarIndex].Length = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64)Value, 32);
1919 PciIoDevice->PciBar[BarIndex].Length = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;
1920 if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {
1921 //
1922 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1923 //
1924 PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);
1925 } else {
1926 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1927 }
1928
1929 break;
1930
1931 //
1932 // reserved
1933 //
1934 default:
1935 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
1936 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
1937 if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {
1938 //
1939 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1940 //
1941 PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);
1942 } else {
1943 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1944 }
1945
1946 break;
1947 }
1948 }
1949
1950 //
1951 // Check the length again so as to keep compatible with some special bars
1952 //
1953 if (PciIoDevice->PciBar[BarIndex].Length == 0) {
1954 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
1955 PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
1956 PciIoDevice->PciBar[BarIndex].Alignment = 0;
1957 }
1958
1959 //
1960 // Increment number of bar
1961 //
1962 return Offset + 4;
1963 }
1964
1965 /**
1966 This routine is used to initialize the bar of a PCI device.
1967
1968 @param PciIoDevice Pci device instance.
1969
1970 @note It can be called typically when a device is going to be rejected.
1971
1972 **/
1973 VOID
1974 InitializePciDevice (
1975 IN PCI_IO_DEVICE *PciIoDevice
1976 )
1977 {
1978 EFI_PCI_IO_PROTOCOL *PciIo;
1979 UINT8 Offset;
1980
1981 PciIo = &(PciIoDevice->PciIo);
1982
1983 //
1984 // Put all the resource apertures
1985 // Resource base is set to all ones so as to indicate its resource
1986 // has not been allocated
1987 //
1988 for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {
1989 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne);
1990 }
1991 }
1992
1993 /**
1994 This routine is used to initialize the bar of a PCI-PCI Bridge device.
1995
1996 @param PciIoDevice PCI-PCI bridge device instance.
1997
1998 **/
1999 VOID
2000 InitializePpb (
2001 IN PCI_IO_DEVICE *PciIoDevice
2002 )
2003 {
2004 EFI_PCI_IO_PROTOCOL *PciIo;
2005
2006 PciIo = &(PciIoDevice->PciIo);
2007
2008 //
2009 // Put all the resource apertures including IO16
2010 // Io32, pMem32, pMem64 to quiescent state
2011 // Resource base all ones, Resource limit all zeros
2012 //
2013 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
2014 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);
2015
2016 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);
2017 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);
2018
2019 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);
2020 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);
2021
2022 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);
2023 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);
2024
2025 //
2026 // Don't support use io32 as for now
2027 //
2028 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);
2029 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);
2030
2031 //
2032 // Force Interrupt line to zero for cards that come up randomly
2033 //
2034 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
2035 }
2036
2037 /**
2038 This routine is used to initialize the bar of a PCI Card Bridge device.
2039
2040 @param PciIoDevice PCI Card bridge device.
2041
2042 **/
2043 VOID
2044 InitializeP2C (
2045 IN PCI_IO_DEVICE *PciIoDevice
2046 )
2047 {
2048 EFI_PCI_IO_PROTOCOL *PciIo;
2049
2050 PciIo = &(PciIoDevice->PciIo);
2051
2052 //
2053 // Put all the resource apertures including IO16
2054 // Io32, pMem32, pMem64 to quiescent state(
2055 // Resource base all ones, Resource limit all zeros
2056 //
2057 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);
2058 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);
2059
2060 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);
2061 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);
2062
2063 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);
2064 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);
2065
2066 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);
2067 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);
2068
2069 //
2070 // Force Interrupt line to zero for cards that come up randomly
2071 //
2072 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
2073 }
2074
2075 /**
2076 Authenticate the PCI device by using DeviceSecurityProtocol.
2077
2078 @param PciIoDevice PCI device.
2079
2080 @retval EFI_SUCCESS The device passes the authentication.
2081 @return not EFI_SUCCESS The device failes the authentication or
2082 unexpected error happen during authentication.
2083 **/
2084 EFI_STATUS
2085 AuthenticatePciDevice (
2086 IN PCI_IO_DEVICE *PciIoDevice
2087 )
2088 {
2089 EDKII_DEVICE_IDENTIFIER DeviceIdentifier;
2090 EFI_STATUS Status;
2091
2092 if (mDeviceSecurityProtocol != NULL) {
2093 //
2094 // Prepare the parameter
2095 //
2096 DeviceIdentifier.Version = EDKII_DEVICE_IDENTIFIER_REVISION;
2097 CopyGuid (&DeviceIdentifier.DeviceType, &gEdkiiDeviceIdentifierTypePciGuid);
2098 DeviceIdentifier.DeviceHandle = NULL;
2099 Status = gBS->InstallMultipleProtocolInterfaces (
2100 &DeviceIdentifier.DeviceHandle,
2101 &gEfiDevicePathProtocolGuid,
2102 PciIoDevice->DevicePath,
2103 &gEdkiiDeviceIdentifierTypePciGuid,
2104 &PciIoDevice->PciIo,
2105 NULL
2106 );
2107 if (EFI_ERROR (Status)) {
2108 return Status;
2109 }
2110
2111 //
2112 // Do DeviceAuthentication
2113 //
2114 Status = mDeviceSecurityProtocol->DeviceAuthenticate (mDeviceSecurityProtocol, &DeviceIdentifier);
2115 //
2116 // Always uninstall, because they are only for Authentication.
2117 // No need to check return Status.
2118 //
2119 gBS->UninstallMultipleProtocolInterfaces (
2120 DeviceIdentifier.DeviceHandle,
2121 &gEfiDevicePathProtocolGuid,
2122 PciIoDevice->DevicePath,
2123 &gEdkiiDeviceIdentifierTypePciGuid,
2124 &PciIoDevice->PciIo,
2125 NULL
2126 );
2127 return Status;
2128 }
2129
2130 //
2131 // Device Security Protocol is not found, just return success
2132 //
2133 return EFI_SUCCESS;
2134 }
2135
2136 /**
2137 Checks if PCI device is Root Bridge.
2138
2139 @param PciIoDevice Instance of PCI device
2140
2141 @retval TRUE Device is Root Bridge
2142 @retval FALSE Device is not Root Bridge
2143
2144 **/
2145 BOOLEAN
2146 IsRootBridge (
2147 IN PCI_IO_DEVICE *PciIoDevice
2148 )
2149 {
2150 if (PciIoDevice->Parent == NULL) {
2151 return TRUE;
2152 } else {
2153 return FALSE;
2154 }
2155 }
2156
2157 /**
2158 Create and initialize general PCI I/O device instance for
2159 PCI device/bridge device/hotplug bridge device.
2160
2161 @param Bridge Parent bridge instance.
2162 @param Pci Input Pci information block.
2163 @param Bus Device Bus NO.
2164 @param Device Device device NO.
2165 @param Func Device func NO.
2166
2167 @return Instance of PCI device. NULL means no instance created.
2168
2169 **/
2170 PCI_IO_DEVICE *
2171 CreatePciIoDevice (
2172 IN PCI_IO_DEVICE *Bridge,
2173 IN PCI_TYPE00 *Pci,
2174 IN UINT8 Bus,
2175 IN UINT8 Device,
2176 IN UINT8 Func
2177 )
2178 {
2179 PCI_IO_DEVICE *PciIoDevice;
2180 EFI_PCI_IO_PROTOCOL *PciIo;
2181 EFI_STATUS Status;
2182
2183 PciIoDevice = AllocateZeroPool (sizeof (PCI_IO_DEVICE));
2184 if (PciIoDevice == NULL) {
2185 return NULL;
2186 }
2187
2188 PciIoDevice->Signature = PCI_IO_DEVICE_SIGNATURE;
2189 PciIoDevice->Handle = NULL;
2190 PciIoDevice->PciRootBridgeIo = Bridge->PciRootBridgeIo;
2191 PciIoDevice->DevicePath = NULL;
2192 PciIoDevice->BusNumber = Bus;
2193 PciIoDevice->DeviceNumber = Device;
2194 PciIoDevice->FunctionNumber = Func;
2195 PciIoDevice->Decodes = 0;
2196
2197 if (gFullEnumeration) {
2198 PciIoDevice->Allocated = FALSE;
2199 } else {
2200 PciIoDevice->Allocated = TRUE;
2201 }
2202
2203 PciIoDevice->Registered = FALSE;
2204 PciIoDevice->Attributes = 0;
2205 PciIoDevice->Supports = 0;
2206 PciIoDevice->BusOverride = FALSE;
2207 PciIoDevice->AllOpRomProcessed = FALSE;
2208
2209 PciIoDevice->IsPciExp = FALSE;
2210
2211 CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));
2212
2213 //
2214 // Initialize the PCI I/O instance structure
2215 //
2216 InitializePciIoInstance (PciIoDevice);
2217 InitializePciDriverOverrideInstance (PciIoDevice);
2218 InitializePciLoadFile2 (PciIoDevice);
2219 PciIo = &PciIoDevice->PciIo;
2220
2221 //
2222 // Create a device path for this PCI device and store it into its private data
2223 //
2224 CreatePciDevicePath (
2225 Bridge->DevicePath,
2226 PciIoDevice
2227 );
2228
2229 //
2230 // Detect if PCI Express Device
2231 //
2232 PciIoDevice->PciExpressCapabilityOffset = 0;
2233 Status = LocateCapabilityRegBlock (
2234 PciIoDevice,
2235 EFI_PCI_CAPABILITY_ID_PCIEXP,
2236 &PciIoDevice->PciExpressCapabilityOffset,
2237 NULL
2238 );
2239 if (!EFI_ERROR (Status)) {
2240 PciIoDevice->IsPciExp = TRUE;
2241 }
2242
2243 //
2244 // Now we can do the authentication check for the device.
2245 //
2246 Status = AuthenticatePciDevice (PciIoDevice);
2247 //
2248 // If authentication fails, skip this device.
2249 //
2250 if (EFI_ERROR (Status)) {
2251 if (PciIoDevice->DevicePath != NULL) {
2252 FreePool (PciIoDevice->DevicePath);
2253 }
2254
2255 FreePool (PciIoDevice);
2256 return NULL;
2257 }
2258
2259 //
2260 // Check if device's parent is not Root Bridge
2261 //
2262 if (PcdGetBool (PcdAriSupport) && !IsRootBridge (Bridge)) {
2263 //
2264 // Check if the device is an ARI device.
2265 //
2266 Status = LocatePciExpressCapabilityRegBlock (
2267 PciIoDevice,
2268 EFI_PCIE_CAPABILITY_ID_ARI,
2269 &PciIoDevice->AriCapabilityOffset,
2270 NULL
2271 );
2272 if (!EFI_ERROR (Status)) {
2273 //
2274 // We need to enable ARI feature before calculate BusReservation,
2275 // because FirstVFOffset and VFStride may change after that.
2276 //
2277 EFI_PCI_IO_PROTOCOL *ParentPciIo;
2278 UINT32 Data32;
2279
2280 //
2281 // Check if its parent supports ARI forwarding.
2282 //
2283 ParentPciIo = &Bridge->PciIo;
2284 ParentPciIo->Pci.Read (
2285 ParentPciIo,
2286 EfiPciIoWidthUint32,
2287 Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET,
2288 1,
2289 &Data32
2290 );
2291 if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING) != 0) {
2292 PciIoDevice->IsAriEnabled = TRUE;
2293 //
2294 // ARI forward support in bridge, so enable it.
2295 //
2296 ParentPciIo->Pci.Read (
2297 ParentPciIo,
2298 EfiPciIoWidthUint32,
2299 Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET,
2300 1,
2301 &Data32
2302 );
2303 if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING) == 0) {
2304 Data32 |= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING;
2305 ParentPciIo->Pci.Write (
2306 ParentPciIo,
2307 EfiPciIoWidthUint32,
2308 Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET,
2309 1,
2310 &Data32
2311 );
2312 DEBUG ((
2313 DEBUG_INFO,
2314 " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",
2315 Bridge->BusNumber,
2316 Bridge->DeviceNumber,
2317 Bridge->FunctionNumber
2318 ));
2319 }
2320 }
2321
2322 DEBUG ((DEBUG_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice->AriCapabilityOffset));
2323 }
2324 }
2325
2326 //
2327 // Initialization for SR-IOV
2328 //
2329
2330 if (PcdGetBool (PcdSrIovSupport)) {
2331 Status = LocatePciExpressCapabilityRegBlock (
2332 PciIoDevice,
2333 EFI_PCIE_CAPABILITY_ID_SRIOV,
2334 &PciIoDevice->SrIovCapabilityOffset,
2335 NULL
2336 );
2337 if (!EFI_ERROR (Status)) {
2338 UINT32 SupportedPageSize;
2339 UINT16 VFStride;
2340 UINT16 FirstVFOffset;
2341 UINT16 Data16;
2342 UINT32 PFRid;
2343 UINT32 LastVF;
2344
2345 //
2346 // If the SR-IOV device is an ARI device, then Set ARI Capable Hierarchy for the device.
2347 //
2348 if (PcdGetBool (PcdAriSupport) && (PciIoDevice->AriCapabilityOffset != 0)) {
2349 PciIo->Pci.Read (
2350 PciIo,
2351 EfiPciIoWidthUint16,
2352 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL,
2353 1,
2354 &Data16
2355 );
2356 Data16 |= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY;
2357 PciIo->Pci.Write (
2358 PciIo,
2359 EfiPciIoWidthUint16,
2360 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL,
2361 1,
2362 &Data16
2363 );
2364 }
2365
2366 //
2367 // Calculate SystemPageSize
2368 //
2369
2370 PciIo->Pci.Read (
2371 PciIo,
2372 EfiPciIoWidthUint32,
2373 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE,
2374 1,
2375 &SupportedPageSize
2376 );
2377 PciIoDevice->SystemPageSize = (PcdGet32 (PcdSrIovSystemPageSize) & SupportedPageSize);
2378 ASSERT (PciIoDevice->SystemPageSize != 0);
2379
2380 PciIo->Pci.Write (
2381 PciIo,
2382 EfiPciIoWidthUint32,
2383 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE,
2384 1,
2385 &PciIoDevice->SystemPageSize
2386 );
2387 //
2388 // Adjust SystemPageSize for Alignment usage later
2389 //
2390 PciIoDevice->SystemPageSize <<= 12;
2391
2392 //
2393 // Calculate BusReservation for PCI IOV
2394 //
2395
2396 //
2397 // Read First FirstVFOffset, InitialVFs, and VFStride
2398 //
2399 PciIo->Pci.Read (
2400 PciIo,
2401 EfiPciIoWidthUint16,
2402 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF,
2403 1,
2404 &FirstVFOffset
2405 );
2406 PciIo->Pci.Read (
2407 PciIo,
2408 EfiPciIoWidthUint16,
2409 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS,
2410 1,
2411 &PciIoDevice->InitialVFs
2412 );
2413 PciIo->Pci.Read (
2414 PciIo,
2415 EfiPciIoWidthUint16,
2416 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE,
2417 1,
2418 &VFStride
2419 );
2420 //
2421 // Calculate LastVF
2422 //
2423 if (PciIoDevice->InitialVFs == 0) {
2424 PciIoDevice->ReservedBusNum = 0;
2425 } else {
2426 PFRid = EFI_PCI_RID (Bus, Device, Func);
2427 LastVF = PFRid + FirstVFOffset + (PciIoDevice->InitialVFs - 1) * VFStride;
2428
2429 //
2430 // Calculate ReservedBusNum for this PF
2431 //
2432 PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID (LastVF) - Bus);
2433 }
2434
2435 DEBUG ((
2436 DEBUG_INFO,
2437 " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x; FirstVFOffset = 0x%x;\n",
2438 SupportedPageSize,
2439 PciIoDevice->SystemPageSize >> 12,
2440 FirstVFOffset
2441 ));
2442 DEBUG ((
2443 DEBUG_INFO,
2444 " InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset = 0x%x\n",
2445 PciIoDevice->InitialVFs,
2446 PciIoDevice->ReservedBusNum,
2447 PciIoDevice->SrIovCapabilityOffset
2448 ));
2449 }
2450 }
2451
2452 if (PcdGetBool (PcdMrIovSupport)) {
2453 Status = LocatePciExpressCapabilityRegBlock (
2454 PciIoDevice,
2455 EFI_PCIE_CAPABILITY_ID_MRIOV,
2456 &PciIoDevice->MrIovCapabilityOffset,
2457 NULL
2458 );
2459 if (!EFI_ERROR (Status)) {
2460 DEBUG ((DEBUG_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice->MrIovCapabilityOffset));
2461 }
2462 }
2463
2464 PciIoDevice->ResizableBarOffset = 0;
2465 if (PcdGetBool (PcdPcieResizableBarSupport)) {
2466 Status = LocatePciExpressCapabilityRegBlock (
2467 PciIoDevice,
2468 PCI_EXPRESS_EXTENDED_CAPABILITY_RESIZABLE_BAR_ID,
2469 &PciIoDevice->ResizableBarOffset,
2470 NULL
2471 );
2472 if (!EFI_ERROR (Status)) {
2473 PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CONTROL ResizableBarControl;
2474 UINT32 Offset;
2475 Offset = PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER)
2476 + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CAPABILITY),
2477 PciIo->Pci.Read (
2478 PciIo,
2479 EfiPciIoWidthUint8,
2480 Offset,
2481 sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CONTROL),
2482 &ResizableBarControl
2483 );
2484 PciIoDevice->ResizableBarNumber = ResizableBarControl.Bits.ResizableBarNumber;
2485 PciProgramResizableBar (PciIoDevice, PciResizableBarMax);
2486 }
2487 }
2488
2489 //
2490 // Initialize the reserved resource list
2491 //
2492 InitializeListHead (&PciIoDevice->ReservedResourceList);
2493
2494 //
2495 // Initialize the driver list
2496 //
2497 InitializeListHead (&PciIoDevice->OptionRomDriverList);
2498
2499 //
2500 // Initialize the child list
2501 //
2502 InitializeListHead (&PciIoDevice->ChildList);
2503
2504 return PciIoDevice;
2505 }
2506
2507 /**
2508 This routine is used to enumerate entire pci bus system
2509 in a given platform.
2510
2511 It is only called on the second start on the same Root Bridge.
2512
2513 @param Controller Parent bridge handler.
2514
2515 @retval EFI_SUCCESS PCI enumeration finished successfully.
2516 @retval other Some error occurred when enumerating the pci bus system.
2517
2518 **/
2519 EFI_STATUS
2520 PciEnumeratorLight (
2521 IN EFI_HANDLE Controller
2522 )
2523 {
2524 EFI_STATUS Status;
2525 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
2526 PCI_IO_DEVICE *RootBridgeDev;
2527 UINT16 MinBus;
2528 UINT16 MaxBus;
2529 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
2530
2531 MinBus = 0;
2532 MaxBus = PCI_MAX_BUS;
2533 Descriptors = NULL;
2534
2535 //
2536 // If this root bridge has been already enumerated, then return successfully
2537 //
2538 if (GetRootBridgeByHandle (Controller) != NULL) {
2539 return EFI_SUCCESS;
2540 }
2541
2542 //
2543 // Open pci root bridge io protocol
2544 //
2545 Status = gBS->OpenProtocol (
2546 Controller,
2547 &gEfiPciRootBridgeIoProtocolGuid,
2548 (VOID **)&PciRootBridgeIo,
2549 gPciBusDriverBinding.DriverBindingHandle,
2550 Controller,
2551 EFI_OPEN_PROTOCOL_BY_DRIVER
2552 );
2553 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
2554 return Status;
2555 }
2556
2557 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **)&Descriptors);
2558
2559 if (EFI_ERROR (Status)) {
2560 return Status;
2561 }
2562
2563 while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {
2564 //
2565 // Create a device node for root bridge device with a NULL host bridge controller handle
2566 //
2567 RootBridgeDev = CreateRootBridge (Controller);
2568
2569 if (RootBridgeDev == NULL) {
2570 Descriptors++;
2571 continue;
2572 }
2573
2574 //
2575 // Record the root bridge-io protocol
2576 //
2577 RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
2578
2579 Status = PciPciDeviceInfoCollector (
2580 RootBridgeDev,
2581 (UINT8)MinBus
2582 );
2583
2584 if (!EFI_ERROR (Status)) {
2585 //
2586 // Remove those PCI devices which are rejected when full enumeration
2587 //
2588 RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev);
2589
2590 //
2591 // Process option rom light
2592 //
2593 ProcessOptionRomLight (RootBridgeDev);
2594
2595 //
2596 // Determine attributes for all devices under this root bridge
2597 //
2598 DetermineDeviceAttribute (RootBridgeDev);
2599
2600 //
2601 // If successfully, insert the node into device pool
2602 //
2603 InsertRootBridge (RootBridgeDev);
2604 } else {
2605 //
2606 // If unsuccessfully, destroy the entire node
2607 //
2608 DestroyRootBridge (RootBridgeDev);
2609 }
2610
2611 Descriptors++;
2612 }
2613
2614 return EFI_SUCCESS;
2615 }
2616
2617 /**
2618 Get bus range from PCI resource descriptor list.
2619
2620 @param Descriptors A pointer to the address space descriptor.
2621 @param MinBus The min bus returned.
2622 @param MaxBus The max bus returned.
2623 @param BusRange The bus range returned.
2624
2625 @retval EFI_SUCCESS Successfully got bus range.
2626 @retval EFI_NOT_FOUND Can not find the specific bus.
2627
2628 **/
2629 EFI_STATUS
2630 PciGetBusRange (
2631 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
2632 OUT UINT16 *MinBus,
2633 OUT UINT16 *MaxBus,
2634 OUT UINT16 *BusRange
2635 )
2636 {
2637 while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {
2638 if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
2639 if (MinBus != NULL) {
2640 *MinBus = (UINT16)(*Descriptors)->AddrRangeMin;
2641 }
2642
2643 if (MaxBus != NULL) {
2644 *MaxBus = (UINT16)(*Descriptors)->AddrRangeMax;
2645 }
2646
2647 if (BusRange != NULL) {
2648 *BusRange = (UINT16)(*Descriptors)->AddrLen;
2649 }
2650
2651 return EFI_SUCCESS;
2652 }
2653
2654 (*Descriptors)++;
2655 }
2656
2657 return EFI_NOT_FOUND;
2658 }
2659
2660 /**
2661 This routine can be used to start the root bridge.
2662
2663 @param RootBridgeDev Pci device instance.
2664
2665 @retval EFI_SUCCESS This device started.
2666 @retval other Failed to get PCI Root Bridge I/O protocol.
2667
2668 **/
2669 EFI_STATUS
2670 StartManagingRootBridge (
2671 IN PCI_IO_DEVICE *RootBridgeDev
2672 )
2673 {
2674 EFI_HANDLE RootBridgeHandle;
2675 EFI_STATUS Status;
2676 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
2677
2678 //
2679 // Get the root bridge handle
2680 //
2681 RootBridgeHandle = RootBridgeDev->Handle;
2682 PciRootBridgeIo = NULL;
2683
2684 //
2685 // Get the pci root bridge io protocol
2686 //
2687 Status = gBS->OpenProtocol (
2688 RootBridgeHandle,
2689 &gEfiPciRootBridgeIoProtocolGuid,
2690 (VOID **)&PciRootBridgeIo,
2691 gPciBusDriverBinding.DriverBindingHandle,
2692 RootBridgeHandle,
2693 EFI_OPEN_PROTOCOL_BY_DRIVER
2694 );
2695
2696 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
2697 return Status;
2698 }
2699
2700 //
2701 // Store the PciRootBridgeIo protocol into root bridge private data
2702 //
2703 RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
2704
2705 return EFI_SUCCESS;
2706 }
2707
2708 /**
2709 This routine can be used to check whether a PCI device should be rejected when light enumeration.
2710
2711 @param PciIoDevice Pci device instance.
2712
2713 @retval TRUE This device should be rejected.
2714 @retval FALSE This device shouldn't be rejected.
2715
2716 **/
2717 BOOLEAN
2718 IsPciDeviceRejected (
2719 IN PCI_IO_DEVICE *PciIoDevice
2720 )
2721 {
2722 EFI_STATUS Status;
2723 UINT32 TestValue;
2724 UINT32 OldValue;
2725 UINT32 Mask;
2726 UINT8 BarOffset;
2727
2728 //
2729 // PPB should be skip!
2730 //
2731 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
2732 return FALSE;
2733 }
2734
2735 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
2736 //
2737 // Only test base registers for P2C
2738 //
2739 for (BarOffset = 0x1C; BarOffset <= 0x38; BarOffset += 2 * sizeof (UINT32)) {
2740 Mask = (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;
2741 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
2742 if (EFI_ERROR (Status)) {
2743 continue;
2744 }
2745
2746 TestValue = TestValue & Mask;
2747 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
2748 //
2749 // The bar isn't programed, so it should be rejected
2750 //
2751 return TRUE;
2752 }
2753 }
2754
2755 return FALSE;
2756 }
2757
2758 for (BarOffset = 0x14; BarOffset <= 0x24; BarOffset += sizeof (UINT32)) {
2759 //
2760 // Test PCI devices
2761 //
2762 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
2763 if (EFI_ERROR (Status)) {
2764 continue;
2765 }
2766
2767 if ((TestValue & 0x01) != 0) {
2768 //
2769 // IO Bar
2770 //
2771 Mask = 0xFFFFFFFC;
2772 TestValue = TestValue & Mask;
2773 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
2774 return TRUE;
2775 }
2776 } else {
2777 //
2778 // Mem Bar
2779 //
2780 Mask = 0xFFFFFFF0;
2781 TestValue = TestValue & Mask;
2782
2783 if ((TestValue & 0x07) == 0x04) {
2784 //
2785 // Mem64 or PMem64
2786 //
2787 BarOffset += sizeof (UINT32);
2788 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
2789 //
2790 // Test its high 32-Bit BAR
2791 //
2792 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
2793 if (TestValue == OldValue) {
2794 return TRUE;
2795 }
2796 }
2797 } else {
2798 //
2799 // Mem32 or PMem32
2800 //
2801 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
2802 return TRUE;
2803 }
2804 }
2805 }
2806 }
2807
2808 return FALSE;
2809 }
2810
2811 /**
2812 Reset all bus number from specific bridge.
2813
2814 @param Bridge Parent specific bridge.
2815 @param StartBusNumber Start bus number.
2816
2817 **/
2818 VOID
2819 ResetAllPpbBusNumber (
2820 IN PCI_IO_DEVICE *Bridge,
2821 IN UINT8 StartBusNumber
2822 )
2823 {
2824 EFI_STATUS Status;
2825 PCI_TYPE00 Pci;
2826 UINT8 Device;
2827 UINT32 Register;
2828 UINT8 Func;
2829 UINT64 Address;
2830 UINT8 SecondaryBus;
2831 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
2832
2833 PciRootBridgeIo = Bridge->PciRootBridgeIo;
2834
2835 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
2836 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
2837 //
2838 // Check to see whether a pci device is present
2839 //
2840 Status = PciDevicePresent (
2841 PciRootBridgeIo,
2842 &Pci,
2843 StartBusNumber,
2844 Device,
2845 Func
2846 );
2847
2848 if (EFI_ERROR (Status) && (Func == 0)) {
2849 //
2850 // go to next device if there is no Function 0
2851 //
2852 break;
2853 }
2854
2855 if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) {
2856 Register = 0;
2857 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
2858 Status = PciRootBridgeIo->Pci.Read (
2859 PciRootBridgeIo,
2860 EfiPciWidthUint32,
2861 Address,
2862 1,
2863 &Register
2864 );
2865 SecondaryBus = (UINT8)(Register >> 8);
2866
2867 if (SecondaryBus != 0) {
2868 ResetAllPpbBusNumber (Bridge, SecondaryBus);
2869 }
2870
2871 //
2872 // Reset register 18h, 19h, 1Ah on PCI Bridge
2873 //
2874 Register &= 0xFF000000;
2875 Status = PciRootBridgeIo->Pci.Write (
2876 PciRootBridgeIo,
2877 EfiPciWidthUint32,
2878 Address,
2879 1,
2880 &Register
2881 );
2882 }
2883
2884 if ((Func == 0) && !IS_PCI_MULTI_FUNC (&Pci)) {
2885 //
2886 // Skip sub functions, this is not a multi function device
2887 //
2888 Func = PCI_MAX_FUNC;
2889 }
2890 }
2891 }
2892 }