OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
SetResizableBar.c
Go to the documentation of this file.
1
15#include <Uefi.h>
16
17#include <IndustryStandard/Pci.h>
18
19#include <Protocol/PciIo.h>
20#include <Protocol/PciRootBridgeIo.h>
21
22#include <Library/BaseLib.h>
23#include <Library/BaseMemoryLib.h>
24#include <Library/MemoryAllocationLib.h>
25#include <Library/DebugLib.h>
26#include <Library/IoLib.h>
27#include <Library/UefiBootServicesTableLib.h>
29
30#include "PciExtInternal.h"
31
32STATIC
33EFI_STATUS
35 IN EFI_PCI_IO_PROTOCOL *PciIo,
36 IN UINT16 CapId,
37 OUT UINT32 *Offset
38 )
39{
40 EFI_STATUS Status;
41 UINT32 CapabilityPtr;
42 UINT32 CapabilityEntry;
43 UINT16 CapabilityID;
44
45 CapabilityPtr = EFI_PCIE_CAPABILITY_BASE_OFFSET;
46
47 while (CapabilityPtr != 0) {
48 //
49 // Mask it to DWORD alignment per PCI spec
50 //
51 CapabilityPtr &= 0xFFC;
52 Status = PciIo->Pci.Read (
53 PciIo,
54 EfiPciIoWidthUint32,
55 CapabilityPtr,
56 1,
57 &CapabilityEntry
58 );
59 if (EFI_ERROR (Status)) {
60 DEBUG ((DEBUG_INFO, "OCDM: Capability I/O error - %r\n", Status));
61 return EFI_DEVICE_ERROR;
62 }
63
64 if (CapabilityEntry == MAX_UINT32) {
65 DEBUG ((DEBUG_INFO, "OCDM: Read from disabled device\n"));
66 return EFI_INVALID_PARAMETER;
67 }
68
69 CapabilityID = (UINT16)CapabilityEntry;
70
71 if (CapabilityID == CapId) {
72 DEBUG ((DEBUG_VERBOSE, "OCDM: Found CAP 0x%X at 0x%X\n", CapabilityID, CapabilityPtr));
73 *Offset = CapabilityPtr;
74 return EFI_SUCCESS;
75 }
76
77 CapabilityPtr = (CapabilityEntry >> 20) & 0xFFF;
78 }
79
80 return EFI_NOT_FOUND;
81}
82
83//
84// Needed to access address larger than 256
85//
86STATIC
87UINT64
89 UINT64 PciAddress,
90 INT32 Offset
91 )
92{
93 UINT32 Reg = (UINT32)((PciAddress & 0xffffffff00000000) >> 32);
94 UINT8 Bus = (UINT8)((PciAddress & 0xff000000) >> 24);
95 UINT8 Dev = (UINT8)((PciAddress & 0xff0000) >> 16);
96 UINT8 Func = (UINT8)((PciAddress & 0xff00) >> 8);
97
98 return EFI_PCI_ADDRESS (Bus, Dev, Func, (Reg + Offset));
99}
100
101STATIC
102EFI_STATUS
104 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
105 IN UINT64 PciAddress,
106 IN UINT16 CapId,
107 OUT UINT32 *Offset
108 )
109{
110 EFI_STATUS Status;
111 UINT32 CapabilityPtr;
112 UINT32 CapabilityEntry;
113 UINT16 CapabilityID;
114
115 CapabilityPtr = EFI_PCIE_CAPABILITY_BASE_OFFSET;
116
117 while (CapabilityPtr != 0) {
118 //
119 // Mask it to DWORD alignment per PCI spec
120 //
121 CapabilityPtr &= 0xFFC;
122 Status = PciRootBridgeIo->Pci.Read (
123 PciRootBridgeIo,
124 EfiPciWidthUint32,
125 PciAddrOffset (PciAddress, CapabilityPtr),
126 1,
127 &CapabilityEntry
128 );
129 if (EFI_ERROR (Status)) {
130 DEBUG ((DEBUG_INFO, "OCDM: Capability I/O error - %r\n", Status));
131 return EFI_DEVICE_ERROR;
132 }
133
134 if (CapabilityEntry == MAX_UINT32) {
135 DEBUG ((DEBUG_INFO, "OCDM: Read from disabled device\n"));
136 return EFI_INVALID_PARAMETER;
137 }
138
139 CapabilityID = (UINT16)CapabilityEntry;
140
141 if (CapabilityID == CapId) {
142 DEBUG ((DEBUG_VERBOSE, "OCDM: Found CAP 0x%X at 0x%X\n", CapabilityID, CapabilityPtr));
143 *Offset = CapabilityPtr;
144 return EFI_SUCCESS;
145 }
146
147 CapabilityPtr = (CapabilityEntry >> 20) & 0xFFF;
148 }
149
150 return EFI_NOT_FOUND;
151}
152
153STATIC
154EFI_STATUS
156 IN EFI_PCI_IO_PROTOCOL *PciIo,
158 IN BOOLEAN Increase
159 )
160{
161 EFI_STATUS Status;
162 UINT32 ResizableBarOffset;
163 PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY Entries[PCI_MAX_BAR];
164 PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CONTROL ResizableBarControl;
165 UINT32 Offset;
166 UINT32 Index;
167 UINT32 ResizableBarNumber;
168 UINT64 Capabilities;
169 UINT64 NewCapabilities;
170 UINT32 OldBar[PCI_MAX_BAR];
171 UINT32 NewBar[PCI_MAX_BAR];
172 INTN Bit;
173 BOOLEAN ChangedBars;
174
175 ChangedBars = FALSE;
176
177 Status = LocatePciCapabilityPciIo (
178 PciIo,
179 PCI_EXPRESS_EXTENDED_CAPABILITY_RESIZABLE_BAR_ID,
180 &ResizableBarOffset
181 );
182 if (EFI_ERROR (Status)) {
183 DEBUG ((DEBUG_INFO, "OCDM: RBAR is unsupported by device - %r\n", Status));
184 return EFI_UNSUPPORTED;
185 }
186
187 ResizableBarControl.Uint32 = 0;
188 Offset = ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER)
189 + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CAPABILITY);
190 Status = PciIo->Pci.Read (
191 PciIo,
192 EfiPciIoWidthUint8,
193 Offset,
194 sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CONTROL),
195 &ResizableBarControl
196 );
197
198 DEBUG ((
199 DEBUG_INFO,
200 "OCDM: RBAR control is %X, total %u - %r\n",
201 ResizableBarControl.Uint32,
202 MIN (ResizableBarControl.Bits.ResizableBarNumber, PCI_MAX_BAR),
203 Status
204 ));
205
206 if (EFI_ERROR (Status)) {
207 return EFI_UNSUPPORTED;
208 }
209
210 ResizableBarNumber = MIN (ResizableBarControl.Bits.ResizableBarNumber, PCI_MAX_BAR);
211
212 Status = PciIo->Pci.Read (
213 PciIo,
214 EfiPciIoWidthUint8,
215 ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER),
216 sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY) * ResizableBarNumber,
217 (VOID *)Entries
218 );
219 if (EFI_ERROR (Status)) {
220 DEBUG ((DEBUG_INFO, "OCDM: RBAR caps cannot be read - %r\n", Status));
221 return EFI_UNSUPPORTED;
222 }
223
224 Status = PciIo->Pci.Read (
225 PciIo,
226 EfiPciIoWidthUint32,
227 OFFSET_OF (PCI_TYPE00, Device.Bar),
228 PCI_MAX_BAR,
229 (VOID *)OldBar
230 );
231 if (EFI_ERROR (Status)) {
232 ZeroMem (OldBar, sizeof (OldBar));
233 }
234
235 DEBUG ((
236 DEBUG_INFO,
237 "OCDM: Old BAR %08X %08X %08X %08X %08X %08X - %r\n",
238 OldBar[0],
239 OldBar[1],
240 OldBar[2],
241 OldBar[3],
242 OldBar[4],
243 OldBar[5],
244 Status
245 ));
246
247 for (Index = 0; Index < ResizableBarNumber; Index++) {
248 //
249 // When the bit of Capabilities Set, indicates that the Function supports
250 // operating with the BAR sized to (2^Bit) MB.
251 // Example:
252 // Bit 0 is set: supports operating with the BAR sized to 1 MB
253 // Bit 1 is set: supports operating with the BAR sized to 2 MB
254 // Bit n is set: supports operating with the BAR sized to (2^n) MB
255 //
256 // Reference values for RX 6900 with two resizable BARs.
257 // Disabled values:
258 // Resizeable Bar Capability [1]
259 // ResizableBarCapability 0007F000
260 // ResizableBarControl 0840
261 // Resizeable Bar Capability [2]
262 // ResizableBarCapability 00001FE0
263 // ResizableBarControl 0102
264 // Enabled values:
265 // Resizeable Bar Capability [1]
266 // ResizableBarCapability 0007F000
267 // ResizableBarControl 0E40
268 // Resizeable Bar Capability [2]
269 // ResizableBarCapability 00001FE0
270 // ResizableBarControl 0802
271 //
272 NewCapabilities = Capabilities = LShiftU64 (Entries[Index].ResizableBarControl.Bits.BarSizeCapability, 28)
273 | Entries[Index].ResizableBarCapability.Bits.BarSizeCapability;
274
275 //
276 // Restrict supported BARs to specified value.
277 //
278 NewCapabilities &= PCI_BAR_CAP_LIMIT (Size);
279
280 //
281 // Disable bits higher than current as we are not allowed to increase bar size
282 // more than we already have.
283 //
284 if (!Increase) {
285 NewCapabilities &= PCI_BAR_CAP_LIMIT (Entries[Index].ResizableBarControl.Bits.BarSize);
286 }
287
288 //
289 // If requested BAR size is too low, choose the lowest available BAR size.
290 //
291 if ( (NewCapabilities == 0)
292 && (Entries[Index].ResizableBarControl.Bits.BarSize > (UINT32)Size))
293 {
294 Bit = LowBitSet64 (Capabilities);
295 } else {
296 Bit = HighBitSet64 (NewCapabilities);
297 }
298
299 DEBUG ((
300 DEBUG_INFO,
301 "OCDM: RBAR %u/%u supports 0x%Lx, sizing %u inc %d results setting from %u to %d\n",
302 Index + 1,
303 ResizableBarNumber,
304 Capabilities,
305 Size,
306 Increase,
307 Entries[Index].ResizableBarControl.Bits.BarSize,
308 (INT32)Bit
309 ));
310
311 //
312 // If we have no supported configuration, just skip.
313 //
314 if ((Bit < 0) || (Entries[Index].ResizableBarControl.Bits.BarSize == (UINT32)Bit)) {
315 continue;
316 }
317
318 Offset = ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER)
319 + Index * sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY)
320 + OFFSET_OF (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY, ResizableBarControl);
321
322 Entries[Index].ResizableBarControl.Bits.BarSize = (UINT32)Bit;
323 PciIo->Pci.Write (
324 PciIo,
325 EfiPciIoWidthUint32,
326 Offset,
327 1,
328 &Entries[Index].ResizableBarControl.Uint32
329 );
330
331 ChangedBars = TRUE;
332 }
333
334 if (ChangedBars) {
335 DEBUG_CODE_BEGIN ();
336
337 Status = PciIo->Pci.Read (
338 PciIo,
339 EfiPciIoWidthUint32,
340 OFFSET_OF (PCI_TYPE00, Device.Bar),
341 PCI_MAX_BAR,
342 (VOID *)NewBar
343 );
344 if (EFI_ERROR (Status)) {
345 ZeroMem (NewBar, sizeof (NewBar));
346 }
347
348 DEBUG ((
349 DEBUG_INFO,
350 "OCDM: New BAR %08X %08X %08X %08X %08X %08X - %r\n",
351 NewBar[0],
352 NewBar[1],
353 NewBar[2],
354 NewBar[3],
355 NewBar[4],
356 NewBar[5],
357 Status
358 ));
359
360 DEBUG_CODE_END ();
361
362 //
363 // PCI BARs are reset after resizing, so we must restore them. This follows the spec:
364 // After writing the BAR Size field, the contents of the corresponding BAR are undefined.
365 // To ensure that it contains a valid address after resizing the BAR, system software must
366 // reprogram the BAR, and Set the Memory Space Enable bit (unless the resource is not allocated).
367 // TODO: We do not bother touching `Memory Space Enable` bit but strictly we should.
368 //
369 if (!IsZeroBuffer (OldBar, sizeof (OldBar))) {
370 Status = PciIo->Pci.Write (
371 PciIo,
372 EfiPciIoWidthUint32,
373 OFFSET_OF (PCI_TYPE00, Device.Bar),
374 PCI_MAX_BAR,
375 (VOID *)OldBar
376 );
377 DEBUG ((DEBUG_INFO, "OCDM: Reprogrammed BARs to original - %r\n", Status));
378 }
379 }
380
381 return EFI_SUCCESS;
382}
383
384STATIC
385EFI_STATUS
387 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
388 IN UINT64 PciAddress,
390 IN BOOLEAN Increase
391 )
392{
393 EFI_STATUS Status;
394 UINT32 ResizableBarOffset;
395 PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY Entries[PCI_MAX_BAR];
396 PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CONTROL ResizableBarControl;
397 UINT32 Offset;
398 UINT32 Index;
399 UINT32 ResizableBarNumber;
400 UINT64 Capabilities;
401 UINT64 NewCapabilities;
402 UINT32 OldBar[PCI_MAX_BAR];
403 UINT32 NewBar[PCI_MAX_BAR];
404 INTN Bit;
405
406 Status = LocatePciCapabilityRbIo (
407 PciRootBridgeIo,
408 PciAddress,
409 PCI_EXPRESS_EXTENDED_CAPABILITY_RESIZABLE_BAR_ID,
410 &ResizableBarOffset
411 );
412 if (EFI_ERROR (Status)) {
413 DEBUG ((DEBUG_INFO, "OCDM: RBAR is unsupported by device - %r\n", Status));
414 return EFI_UNSUPPORTED;
415 }
416
417 ResizableBarControl.Uint32 = 0;
418 Offset = ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER)
419 + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CAPABILITY);
420 Status = PciRootBridgeIo->Pci.Read (
421 PciRootBridgeIo,
422 EfiPciWidthUint8,
423 PciAddrOffset (PciAddress, Offset),
424 sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CONTROL),
425 &ResizableBarControl
426 );
427
428 DEBUG ((
429 DEBUG_INFO,
430 "OCDM: RBAR control is %X, total %u - %r\n",
431 ResizableBarControl.Uint32,
432 MIN (ResizableBarControl.Bits.ResizableBarNumber, PCI_MAX_BAR),
433 Status
434 ));
435
436 if (EFI_ERROR (Status)) {
437 return EFI_UNSUPPORTED;
438 }
439
440 ResizableBarNumber = MIN (ResizableBarControl.Bits.ResizableBarNumber, PCI_MAX_BAR);
441
442 Status = PciRootBridgeIo->Pci.Read (
443 PciRootBridgeIo,
444 EfiPciWidthUint8,
445 PciAddrOffset (PciAddress, ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER)),
446 sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY) * ResizableBarNumber,
447 Entries
448 );
449 if (EFI_ERROR (Status)) {
450 DEBUG ((DEBUG_INFO, "OCDM: RBAR caps cannot be read - %r\n", Status));
451 return EFI_UNSUPPORTED;
452 }
453
454 Status = PciRootBridgeIo->Pci.Read (
455 PciRootBridgeIo,
456 EfiPciWidthUint32,
457 PciAddrOffset (PciAddress, OFFSET_OF (PCI_TYPE00, Device.Bar)),
458 PCI_MAX_BAR,
459 OldBar
460 );
461 if (EFI_ERROR (Status)) {
462 ZeroMem (OldBar, sizeof (OldBar));
463 }
464
465 DEBUG ((
466 DEBUG_INFO,
467 "OCDM: Old BAR %08X %08X %08X %08X %08X %08X - %r\n",
468 OldBar[0],
469 OldBar[1],
470 OldBar[2],
471 OldBar[3],
472 OldBar[4],
473 OldBar[5],
474 Status
475 ));
476
477 for (Index = 0; Index < ResizableBarNumber; Index++) {
478 //
479 // When the bit of Capabilities Set, indicates that the Function supports
480 // operating with the BAR sized to (2^Bit) MB.
481 // Example:
482 // Bit 0 is set: supports operating with the BAR sized to 1 MB
483 // Bit 1 is set: supports operating with the BAR sized to 2 MB
484 // Bit n is set: supports operating with the BAR sized to (2^n) MB
485 //
486 // Reference values for RX 6900 with two resizable BARs.
487 // Disabled values:
488 // Resizeable Bar Capability [1]
489 // ResizableBarCapability 0007F000
490 // ResizableBarControl 0840
491 // Resizeable Bar Capability [2]
492 // ResizableBarCapability 00001FE0
493 // ResizableBarControl 0102
494 // Enabled values:
495 // Resizeable Bar Capability [1]
496 // ResizableBarCapability 0007F000
497 // ResizableBarControl 0E40
498 // Resizeable Bar Capability [2]
499 // ResizableBarCapability 00001FE0
500 // ResizableBarControl 0802
501 //
502 NewCapabilities = Capabilities = LShiftU64 (Entries[Index].ResizableBarControl.Bits.BarSizeCapability, 28)
503 | Entries[Index].ResizableBarCapability.Bits.BarSizeCapability;
504
505 //
506 // Restrict supported BARs to specified value.
507 //
508 NewCapabilities &= PCI_BAR_CAP_LIMIT (Size);
509
510 //
511 // Disable bits higher than current as we are not allowed to increase bar size
512 // more than we already have.
513 //
514 if (!Increase) {
515 NewCapabilities &= PCI_BAR_CAP_LIMIT (Entries[Index].ResizableBarControl.Bits.BarSize);
516 }
517
518 //
519 // If requested BAR size is too low, choose the lowest available BAR size.
520 //
521 if ( (NewCapabilities == 0)
522 && (Entries[Index].ResizableBarControl.Bits.BarSize > (UINT32)Size))
523 {
524 Bit = LowBitSet64 (Capabilities);
525 } else {
526 Bit = HighBitSet64 (NewCapabilities);
527 }
528
529 DEBUG ((
530 DEBUG_INFO,
531 "OCDM: RBAR %u/%u supports 0x%Lx, sizing %u inc %d results setting from %u to %d\n",
532 Index + 1,
533 ResizableBarNumber,
534 Capabilities,
535 Size,
536 Increase,
537 Entries[Index].ResizableBarControl.Bits.BarSize,
538 (INT32)Bit
539 ));
540
541 //
542 // If we have no supported configuration, just skip.
543 //
544 if ((Bit < 0) || (Entries[Index].ResizableBarControl.Bits.BarSize == (UINT32)Bit)) {
545 continue;
546 }
547
548 Offset = ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER)
549 + Index * sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY)
550 + OFFSET_OF (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY, ResizableBarControl);
551
552 Entries[Index].ResizableBarControl.Bits.BarSize = (UINT32)Bit;
553 PciRootBridgeIo->Pci.Write (
554 PciRootBridgeIo,
555 EfiPciWidthUint32,
556 PciAddrOffset (PciAddress, Offset),
557 1,
558 &Entries[Index].ResizableBarControl.Uint32
559 );
560 }
561
562 DEBUG_CODE_BEGIN ();
563
564 Status = PciRootBridgeIo->Pci.Read (
565 PciRootBridgeIo,
566 EfiPciWidthUint32,
567 PciAddrOffset (PciAddress, OFFSET_OF (PCI_TYPE00, Device.Bar)),
568 PCI_MAX_BAR,
569 NewBar
570 );
571 if (EFI_ERROR (Status)) {
572 ZeroMem (NewBar, sizeof (NewBar));
573 }
574
575 DEBUG ((
576 DEBUG_INFO,
577 "OCDM: New BAR %08X %08X %08X %08X %08X %08X - %r\n",
578 NewBar[0],
579 NewBar[1],
580 NewBar[2],
581 NewBar[3],
582 NewBar[4],
583 NewBar[5],
584 Status
585 ));
586
587 DEBUG_CODE_END ();
588
589 //
590 // PCI BARs are reset after resizing, so we must restore them. This follows the spec:
591 // After writing the BAR Size field, the contents of the corresponding BAR are undefined.
592 // To ensure that it contains a valid address after resizing the BAR, system software must
593 // reprogram the BAR, and Set the Memory Space Enable bit (unless the resource is not allocated).
594 // TODO: We do not bother touching `Memory Space Enable` bit but strictly we should.
595 //
596 if (!IsZeroBuffer (OldBar, sizeof (OldBar))) {
597 Status = PciRootBridgeIo->Pci.Write (
598 PciRootBridgeIo,
599 EfiPciWidthUint32,
600 PciAddrOffset (PciAddress, OFFSET_OF (PCI_TYPE00, Device.Bar)),
601 PCI_MAX_BAR,
602 OldBar
603 );
604 DEBUG ((DEBUG_INFO, "OCDM: Reprogrammed BARs to original - %r\n", Status));
605 }
606
607 return EFI_SUCCESS;
608}
609
610EFI_STATUS
613 IN BOOLEAN Increase
614 )
615{
616 EFI_STATUS Status;
617 UINTN HandleCount;
618 EFI_HANDLE *HandleBuffer;
619 UINTN Index;
620 EFI_PCI_IO_PROTOCOL *PciIo;
621 PCI_CLASSCODE ClassCode;
622 BOOLEAN HasSuccess;
623
625
626 HasSuccess = FALSE;
627
628 Status = gBS->LocateHandleBuffer (
629 ByProtocol,
630 &gEfiPciIoProtocolGuid,
631 NULL,
632 &HandleCount,
633 &HandleBuffer
634 );
635
636 if (EFI_ERROR (Status)) {
637 DEBUG ((DEBUG_INFO, "OCDM: No PCI devices for RBAR support - %r\n", Status));
638 return Status;
639 }
640
641 for (Index = 0; Index < HandleCount; ++Index) {
642 Status = gBS->HandleProtocol (
643 HandleBuffer[Index],
644 &gEfiPciIoProtocolGuid,
645 (VOID **)&PciIo
646 );
647
648 if (EFI_ERROR (Status)) {
649 continue;
650 }
651
652 Status = PciIo->Pci.Read (
653 PciIo,
654 EfiPciIoWidthUint8,
655 PCI_CLASSCODE_OFFSET,
656 sizeof (PCI_CLASSCODE) / sizeof (UINT8),
657 &ClassCode
658 );
659 if (EFI_ERROR (Status)) {
660 continue;
661 }
662
663 DEBUG ((DEBUG_VERBOSE, "OCDM: PCI device %u/%u has class %X\n", Index+1, HandleCount, ClassCode));
664
665 if (ClassCode.BaseCode != PCI_CLASS_DISPLAY) {
666 continue;
667 }
668
669 DEBUG ((
670 DEBUG_INFO,
671 "OCDM: Setting RBAR to %u inc %d on %u/%u\n",
672 Size,
673 Increase,
674 Index+1,
675 HandleCount
676 ));
677 Status = SetResizableBarOnDevicePciIo (PciIo, Size, Increase);
678 if (!EFI_ERROR (Status)) {
679 HasSuccess = TRUE;
680 }
681 }
682
683 FreePool (HandleBuffer);
684
685 if (HasSuccess) {
686 return EFI_SUCCESS;
687 }
688
689 return EFI_NOT_FOUND;
690}
691
692STATIC
693BOOLEAN
695 IN OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
696 OUT UINT16 *MinBus,
697 OUT UINT16 *MaxBus
698 )
699{
700 //
701 // When *Descriptors is NULL, Configuration() is not implemented, so assume
702 // range is 0~PCI_MAX_BUS
703 //
704 if ((*Descriptors) == NULL) {
705 *MinBus = 0;
706 *MaxBus = PCI_MAX_BUS;
707 return FALSE;
708 }
709
710 //
711 // *Descriptors points to one or more address space descriptors, which
712 // ends with a end tagged descriptor. Examine each of the descriptors,
713 // if a bus typed one is found and its bus range covers bus, this handle
714 // is the handle we are looking for.
715 //
716
717 while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {
718 if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
719 *MinBus = (UINT16)(*Descriptors)->AddrRangeMin;
720 *MaxBus = (UINT16)(*Descriptors)->AddrRangeMax;
721 (*Descriptors)++;
722 return FALSE;
723 }
724
725 (*Descriptors)++;
726 }
727
728 return TRUE;
729}
730
731STATIC
732EFI_STATUS
735 IN BOOLEAN Increase
736 )
737{
738 EFI_STATUS Status;
739 UINTN HandleCount;
740 EFI_HANDLE *HandleBuffer;
741 UINTN Index;
742 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
743 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
744 UINT8 HdrType;
745 UINT8 Bus;
746 UINT8 Dev;
747 UINT8 Func;
748 UINT16 MinBus;
749 UINT16 MaxBus;
750 BOOLEAN IsEnd;
751 BOOLEAN HasSuccess;
752 PCI_CLASSCODE ClassCode;
753 UINT64 PciAddress;
754
756
757 HasSuccess = FALSE;
758
759 Status = gBS->LocateHandleBuffer (
760 ByProtocol,
762 NULL,
763 &HandleCount,
764 &HandleBuffer
765 );
766
767 if (EFI_ERROR (Status)) {
768 DEBUG ((DEBUG_INFO, "OCDM: No PCI devices for RBAR support - %r\n", Status));
769 return Status;
770 }
771
772 for (Index = 0; Index < HandleCount; ++Index) {
773 Status = gBS->HandleProtocol (
774 HandleBuffer[Index],
776 (VOID **)&PciRootBridgeIo
777 );
778 if (EFI_ERROR (Status)) {
779 continue;
780 }
781
782 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **)&Descriptors);
783 if (EFI_ERROR (Status)) {
784 continue;
785 }
786
787 //
788 // Not sure if multiple root bridge systems even exist but this should support them
789 //
790 while (TRUE) {
791 IsEnd = PciGetNextBusRange (&Descriptors, &MinBus, &MaxBus);
792
793 if (IsEnd || (Descriptors == NULL)) {
794 break;
795 }
796
797 for (Bus = 0; Bus <= MaxBus; Bus++) {
798 for (Dev = 0; Dev <= PCI_MAX_DEVICE; Dev++) {
799 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
800 PciAddress = EFI_PCI_ADDRESS (Bus, Dev, Func, 0);
801
802 // PciAddrOffset doesnt need to be used below 256
803 Status = PciRootBridgeIo->Pci.Read (
804 PciRootBridgeIo,
805 EfiPciWidthUint8,
806 PciAddress + PCI_CLASSCODE_OFFSET,
807 sizeof (PCI_CLASSCODE) / sizeof (UINT8),
808 &ClassCode
809 );
810 if (EFI_ERROR (Status)) {
811 continue;
812 }
813
814 DEBUG ((DEBUG_VERBOSE, "OCDM: PCI device %u/%u/%u has class %X\n", Bus, Dev, Func, ClassCode));
815
816 if (ClassCode.BaseCode != PCI_CLASS_DISPLAY) {
817 continue;
818 }
819
820 DEBUG ((
821 DEBUG_INFO,
822 "OCDM: Setting RBAR to %u inc %d on %u/%u/%u\n",
823 Size,
824 Increase,
825 Bus,
826 Dev,
827 Func
828 ));
829 Status = SetResizableBarOnDeviceRbIo (PciRootBridgeIo, PciAddress, Size, Increase);
830 if (!EFI_ERROR (Status)) {
831 HasSuccess = TRUE;
832 }
833
834 PciRootBridgeIo->Pci.Read (PciRootBridgeIo, EfiPciWidthUint8, PciAddress + PCI_HEADER_TYPE_OFFSET, 1, &HdrType);
835 if (!Func && ((HdrType & HEADER_TYPE_MULTI_FUNCTION) == 0)) {
836 break;
837 }
838 }
839 }
840 }
841 }
842 }
843
844 FreePool (HandleBuffer);
845
846 if (HasSuccess) {
847 return EFI_SUCCESS;
848 }
849
850 return EFI_NOT_FOUND;
851}
852
853EFI_STATUS
856 IN BOOLEAN Increase,
857 IN BOOLEAN UseRbIo
858 )
859{
860 if (UseRbIo) {
861 DEBUG ((DEBUG_INFO, "OCDM: RBAR using PciRootBridgeIo\n"));
862 return ResizeGpuBarsRbIo (Size, Increase);
863 }
864
865 DEBUG ((DEBUG_INFO, "OCDM: RBAR using PciIo\n"));
866 return ResizeGpuBarsPciIo (Size, Increase);
867}
DMG_SIZE_DEVICE_PATH Size
EFI_BOOT_SERVICES * gBS
PCI_BAR_SIZE
@ PciBarTotal
#define PCI_BAR_CAP_LIMIT(BarSize)
STATIC BOOLEAN PciGetNextBusRange(IN OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors, OUT UINT16 *MinBus, OUT UINT16 *MaxBus)
STATIC UINT64 PciAddrOffset(UINT64 PciAddress, INT32 Offset)
EFI_STATUS ResizeGpuBarsPciIo(IN PCI_BAR_SIZE Size, IN BOOLEAN Increase)
STATIC EFI_STATUS LocatePciCapabilityPciIo(IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT16 CapId, OUT UINT32 *Offset)
STATIC EFI_STATUS LocatePciCapabilityRbIo(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, IN UINT64 PciAddress, IN UINT16 CapId, OUT UINT32 *Offset)
STATIC EFI_STATUS SetResizableBarOnDevicePciIo(IN EFI_PCI_IO_PROTOCOL *PciIo, IN PCI_BAR_SIZE Size, IN BOOLEAN Increase)
STATIC EFI_STATUS SetResizableBarOnDeviceRbIo(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, IN UINT64 PciAddress, IN PCI_BAR_SIZE Size, IN BOOLEAN Increase)
EFI_STATUS ResizeGpuBars(IN PCI_BAR_SIZE Size, IN BOOLEAN Increase, IN BOOLEAN UseRbIo)
STATIC EFI_STATUS ResizeGpuBarsRbIo(IN PCI_BAR_SIZE Size, IN BOOLEAN Increase)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
BOOLEAN EFIAPI IsZeroBuffer(IN CONST VOID *Buffer, IN UINTN Length)
EFI_GUID gEfiPciRootBridgeIoProtocolGuid
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition UserMath.c:76
#define ASSERT(x)
Definition coder.h:55
#define MIN(a, b)
Definition deflate.c:1673