]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
Produce all the PciIo & Dpath protocol for all the pci devices under the current...
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciEnumeratorSupport.c
1 /**@file
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 **/
13
14
15 #include "pcibus.h"
16 #include "PciEnumeratorSupport.h"
17 #include "PciCommand.h"
18 #include "PciIo.h"
19
20 EFI_STATUS
21 PciDevicePresent (
22 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
23 PCI_TYPE00 *Pci,
24 UINT8 Bus,
25 UINT8 Device,
26 UINT8 Func
27 )
28 /*++
29
30 Routine Description:
31
32 This routine is used to check whether the pci device is present
33
34 Arguments:
35
36 Returns:
37
38 None
39
40 --*/
41 // TODO: PciRootBridgeIo - add argument and description to function comment
42 // TODO: Pci - add argument and description to function comment
43 // TODO: Bus - add argument and description to function comment
44 // TODO: Device - add argument and description to function comment
45 // TODO: Func - add argument and description to function comment
46 // TODO: EFI_SUCCESS - add return value to function comment
47 // TODO: EFI_NOT_FOUND - add return value to function comment
48 {
49 UINT64 Address;
50 EFI_STATUS Status;
51
52 //
53 // Create PCI address map in terms of Bus, Device and Func
54 //
55 Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
56
57 //
58 // Read the Vendor Id register
59 //
60 Status = PciRootBridgeIoRead (
61 PciRootBridgeIo,
62 NULL,
63 EfiPciWidthUint32,
64 Address,
65 1,
66 Pci
67 );
68
69 if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {
70
71 //
72 // Read the entire config header for the device
73 //
74
75 Status = PciRootBridgeIoRead (
76 PciRootBridgeIo,
77 NULL,
78 EfiPciWidthUint32,
79 Address,
80 sizeof (PCI_TYPE00) / sizeof (UINT32),
81 Pci
82 );
83
84 return EFI_SUCCESS;
85 }
86
87 return EFI_NOT_FOUND;
88 }
89
90 EFI_STATUS
91 PciPciDeviceInfoCollector (
92 IN PCI_IO_DEVICE *Bridge,
93 UINT8 StartBusNumber
94 )
95 /*++
96
97 Routine Description:
98
99 Arguments:
100
101 Returns:
102
103 None
104
105 --*/
106 // TODO: Bridge - add argument and description to function comment
107 // TODO: StartBusNumber - add argument and description to function comment
108 // TODO: EFI_SUCCESS - add return value to function comment
109 {
110 EFI_STATUS Status;
111 PCI_TYPE00 Pci;
112 UINT8 Device;
113 UINT8 Func;
114 UINT8 SecBus;
115 PCI_IO_DEVICE *PciIoDevice;
116 EFI_PCI_IO_PROTOCOL *PciIo;
117
118 Status = EFI_SUCCESS;
119 SecBus = 0;
120
121 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
122
123 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
124
125 //
126 // Check to see whether PCI device is present
127 //
128
129 Status = PciDevicePresent (
130 Bridge->PciRootBridgeIo,
131 &Pci,
132 (UINT8) StartBusNumber,
133 (UINT8) Device,
134 (UINT8) Func
135 );
136
137 if (!EFI_ERROR (Status)) {
138
139 //
140 // Call back to host bridge function
141 //
142 PreprocessController (Bridge, (UINT8) StartBusNumber, Device, Func, EfiPciBeforeResourceCollection);
143
144 //
145 // Collect all the information about the PCI device discovered
146 //
147 Status = PciSearchDevice (
148 Bridge,
149 &Pci,
150 (UINT8) StartBusNumber,
151 Device,
152 Func,
153 &PciIoDevice
154 );
155
156 //
157 // Recursively scan PCI busses on the other side of PCI-PCI bridges
158 //
159 //
160
161 if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {
162
163 //
164 // If it is PPB, we need to get the secondary bus to continue the enumeration
165 //
166 PciIo = &(PciIoDevice->PciIo);
167
168 Status = PciIoRead (PciIo, EfiPciIoWidthUint8, 0x19, 1, &SecBus);
169
170 if (EFI_ERROR (Status)) {
171 return Status;
172 }
173
174 //
175 // Get resource padding for PPB
176 //
177 GetResourcePaddingPpb (PciIoDevice);
178
179 //
180 // Deep enumerate the next level bus
181 //
182 Status = PciPciDeviceInfoCollector (
183 PciIoDevice,
184 (UINT8) (SecBus)
185 );
186
187 }
188
189 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
190
191 //
192 // Skip sub functions, this is not a multi function device
193 //
194 Func = PCI_MAX_FUNC;
195 }
196 }
197
198 }
199 }
200
201 return EFI_SUCCESS;
202 }
203
204 EFI_STATUS
205 PciSearchDevice (
206 IN PCI_IO_DEVICE *Bridge,
207 IN PCI_TYPE00 *Pci,
208 IN UINT8 Bus,
209 IN UINT8 Device,
210 IN UINT8 Func,
211 OUT PCI_IO_DEVICE **PciDevice
212 )
213 /*++
214
215 Routine Description:
216
217 Search required device.
218
219 Arguments:
220
221 Bridge - A pointer to the PCI_IO_DEVICE.
222 Pci - A pointer to the PCI_TYPE00.
223 Bus - Bus number.
224 Device - Device number.
225 Func - Function number.
226 PciDevice - The Required pci device.
227
228 Returns:
229
230 Status code.
231
232 --*/
233 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
234 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
235 // TODO: EFI_SUCCESS - add return value to function comment
236 {
237 PCI_IO_DEVICE *PciIoDevice;
238
239 PciIoDevice = NULL;
240
241 if (!IS_PCI_BRIDGE (Pci)) {
242
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 //
257 // Create private data for Pci Device
258 //
259 PciIoDevice = GatherDeviceInfo (
260 Bridge,
261 Pci,
262 Bus,
263 Device,
264 Func
265 );
266
267 }
268
269 } else {
270
271 //
272 // Create private data for PPB
273 //
274 PciIoDevice = GatherPpbInfo (
275 Bridge,
276 Pci,
277 Bus,
278 Device,
279 Func
280 );
281
282 //
283 // Special initialization for PPB including making the PPB quiet
284 //
285 if ((PciIoDevice != NULL) && gFullEnumeration) {
286 InitializePpb (PciIoDevice);
287 }
288 }
289
290 if (!PciIoDevice) {
291 return EFI_OUT_OF_RESOURCES;
292 }
293
294 //
295 // Update the bar information for this PCI device so as to support some specific device
296 //
297 UpdatePciInfo (PciIoDevice);
298
299 if (PciIoDevice->DevicePath == NULL) {
300 return EFI_OUT_OF_RESOURCES;
301 }
302
303 //
304 // Detect this function has option rom
305 //
306 if (gFullEnumeration) {
307
308 if (!IS_CARDBUS_BRIDGE (Pci)) {
309
310 GetOpRomInfo (PciIoDevice);
311
312 }
313
314 ResetPowerManagementFeature (PciIoDevice);
315
316 }
317
318 //
319 // Insert it into a global tree for future reference
320 //
321 InsertPciDevice (Bridge, PciIoDevice);
322
323 //
324 // Determine PCI device attributes
325 //
326
327 if (PciDevice != NULL) {
328 *PciDevice = PciIoDevice;
329 }
330
331 return EFI_SUCCESS;
332 }
333
334 PCI_IO_DEVICE *
335 GatherDeviceInfo (
336 IN PCI_IO_DEVICE *Bridge,
337 IN PCI_TYPE00 *Pci,
338 UINT8 Bus,
339 UINT8 Device,
340 UINT8 Func
341 )
342 /*++
343
344 Routine Description:
345
346 Arguments:
347
348 Returns:
349
350 None
351
352 --*/
353 // TODO: Bridge - add argument and description to function comment
354 // TODO: Pci - add argument and description to function comment
355 // TODO: Bus - add argument and description to function comment
356 // TODO: Device - add argument and description to function comment
357 // TODO: Func - add argument and description to function comment
358 {
359 UINTN Offset;
360 UINTN BarIndex;
361 PCI_IO_DEVICE *PciIoDevice;
362 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
363
364 PciRootBridgeIo = Bridge->PciRootBridgeIo;
365 PciIoDevice = CreatePciIoDevice (
366 PciRootBridgeIo,
367 Pci,
368 Bus,
369 Device,
370 Func
371 );
372
373 if (!PciIoDevice) {
374 return NULL;
375 }
376
377 //
378 // Create a device path for this PCI device and store it into its private data
379 //
380 CreatePciDevicePath (
381 Bridge->DevicePath,
382 PciIoDevice
383 );
384
385 //
386 // If it is a full enumeration, disconnect the device in advance
387 //
388 if (gFullEnumeration) {
389
390 PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
391
392 }
393
394 //
395 // Start to parse the bars
396 //
397 for (Offset = 0x10, BarIndex = 0; Offset <= 0x24; BarIndex++) {
398 Offset = PciParseBar (PciIoDevice, Offset, BarIndex);
399 }
400
401 return PciIoDevice;
402 }
403
404 PCI_IO_DEVICE *
405 GatherPpbInfo (
406 IN PCI_IO_DEVICE *Bridge,
407 IN PCI_TYPE00 *Pci,
408 UINT8 Bus,
409 UINT8 Device,
410 UINT8 Func
411 )
412 /*++
413
414 Routine Description:
415
416 Arguments:
417
418 Returns:
419
420 None
421
422 --*/
423 // TODO: Bridge - add argument and description to function comment
424 // TODO: Pci - add argument and description to function comment
425 // TODO: Bus - add argument and description to function comment
426 // TODO: Device - add argument and description to function comment
427 // TODO: Func - add argument and description to function comment
428 {
429 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
430 PCI_IO_DEVICE *PciIoDevice;
431 EFI_STATUS Status;
432 UINT32 Value;
433 EFI_PCI_IO_PROTOCOL *PciIo;
434 UINT8 Temp;
435
436 PciRootBridgeIo = Bridge->PciRootBridgeIo;
437 PciIoDevice = CreatePciIoDevice (
438 PciRootBridgeIo,
439 Pci,
440 Bus,
441 Device,
442 Func
443 );
444
445 if (!PciIoDevice) {
446 return NULL;
447 }
448
449 //
450 // Create a device path for this PCI device and store it into its private data
451 //
452 CreatePciDevicePath (
453 Bridge->DevicePath,
454 PciIoDevice
455 );
456
457 if (gFullEnumeration) {
458 PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
459
460 //
461 // Initalize the bridge control register
462 //
463 PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);
464
465 }
466
467 //
468 // PPB can have two BARs
469 //
470 if (PciParseBar (PciIoDevice, 0x10, PPB_BAR_0) == 0x14) {
471 //
472 // Not 64-bit bar
473 //
474 PciParseBar (PciIoDevice, 0x14, PPB_BAR_1);
475 }
476
477 PciIo = &PciIoDevice->PciIo;
478
479 //
480 // Test whether it support 32 decode or not
481 //
482 PciIoRead (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
483 PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
484 PciIoRead (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
485 PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
486
487 if (Value) {
488 if (Value & 0x01) {
489 PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;
490 } else {
491 PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
492 }
493 }
494
495 Status = BarExisted (
496 PciIoDevice,
497 0x24,
498 NULL,
499 NULL
500 );
501
502 //
503 // test if it supports 64 memory or not
504 //
505 if (!EFI_ERROR (Status)) {
506
507 Status = BarExisted (
508 PciIoDevice,
509 0x28,
510 NULL,
511 NULL
512 );
513
514 if (!EFI_ERROR (Status)) {
515 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
516 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
517 } else {
518 PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
519 }
520 }
521
522 //
523 // Memory 32 code is required for ppb
524 //
525 PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
526
527 GetResourcePaddingPpb (PciIoDevice);
528
529 return PciIoDevice;
530 }
531
532 PCI_IO_DEVICE *
533 GatherP2CInfo (
534 IN PCI_IO_DEVICE *Bridge,
535 IN PCI_TYPE00 *Pci,
536 UINT8 Bus,
537 UINT8 Device,
538 UINT8 Func
539 )
540 /*++
541
542 Routine Description:
543
544 Arguments:
545
546 Returns:
547
548 None
549
550 --*/
551 // TODO: Bridge - add argument and description to function comment
552 // TODO: Pci - add argument and description to function comment
553 // TODO: Bus - add argument and description to function comment
554 // TODO: Device - add argument and description to function comment
555 // TODO: Func - add argument and description to function comment
556 {
557 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
558 PCI_IO_DEVICE *PciIoDevice;
559
560 PciRootBridgeIo = Bridge->PciRootBridgeIo;
561 PciIoDevice = CreatePciIoDevice (
562 PciRootBridgeIo,
563 Pci,
564 Bus,
565 Device,
566 Func
567 );
568
569 if (!PciIoDevice) {
570 return NULL;
571 }
572
573 //
574 // Create a device path for this PCI device and store it into its private data
575 //
576 CreatePciDevicePath (
577 Bridge->DevicePath,
578 PciIoDevice
579 );
580
581 if (gFullEnumeration) {
582 PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
583
584 //
585 // Initalize the bridge control register
586 //
587 PciDisableBridgeControlRegister (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);
588
589 }
590 //
591 // P2C only has one bar that is in 0x10
592 //
593 PciParseBar (PciIoDevice, 0x10, P2C_BAR_0);
594
595 //
596 // Read PciBar information from the bar register
597 //
598 GetBackPcCardBar (PciIoDevice);
599 PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED |
600 EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |
601 EFI_BRIDGE_IO32_DECODE_SUPPORTED;
602
603 return PciIoDevice;
604 }
605
606 EFI_DEVICE_PATH_PROTOCOL *
607 CreatePciDevicePath (
608 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
609 IN PCI_IO_DEVICE *PciIoDevice
610 )
611 /*++
612
613 Routine Description:
614
615 Arguments:
616
617 Returns:
618
619 None
620
621 --*/
622 // TODO: ParentDevicePath - add argument and description to function comment
623 // TODO: PciIoDevice - add argument and description to function comment
624 {
625
626 PCI_DEVICE_PATH PciNode;
627
628 //
629 // Create PCI device path
630 //
631 PciNode.Header.Type = HARDWARE_DEVICE_PATH;
632 PciNode.Header.SubType = HW_PCI_DP;
633 SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
634
635 PciNode.Device = PciIoDevice->DeviceNumber;
636 PciNode.Function = PciIoDevice->FunctionNumber;
637 PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);
638
639 return PciIoDevice->DevicePath;
640 }
641
642 EFI_STATUS
643 BarExisted (
644 IN PCI_IO_DEVICE *PciIoDevice,
645 IN UINTN Offset,
646 OUT UINT32 *BarLengthValue,
647 OUT UINT32 *OriginalBarValue
648 )
649 /*++
650
651 Routine Description:
652
653 Check the bar is existed or not.
654
655 Arguments:
656
657 PciIoDevice - A pointer to the PCI_IO_DEVICE.
658 Offset - The offset.
659 BarLengthValue - The bar length value.
660 OriginalBarValue - The original bar value.
661
662 Returns:
663
664 EFI_NOT_FOUND - The bar don't exist.
665 EFI_SUCCESS - The bar exist.
666
667 --*/
668 {
669 EFI_PCI_IO_PROTOCOL *PciIo;
670 UINT32 OriginalValue;
671 UINT32 Value;
672 EFI_TPL OldTpl;
673
674 PciIo = &PciIoDevice->PciIo;
675
676 //
677 // Preserve the original value
678 //
679
680 PciIoRead (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
681
682 //
683 // Raise TPL to high level to disable timer interrupt while the BAR is probed
684 //
685 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
686
687 PciIoWrite (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);
688 PciIoRead (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value);
689
690 //
691 // Write back the original value
692 //
693 PciIoWrite (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
694
695 //
696 // Restore TPL to its original level
697 //
698 gBS->RestoreTPL (OldTpl);
699
700 if (BarLengthValue != NULL) {
701 *BarLengthValue = Value;
702 }
703
704 if (OriginalBarValue != NULL) {
705 *OriginalBarValue = OriginalValue;
706 }
707
708 if (Value == 0) {
709 return EFI_NOT_FOUND;
710 } else {
711 return EFI_SUCCESS;
712 }
713 }
714
715 EFI_STATUS
716 PciTestSupportedAttribute (
717 IN PCI_IO_DEVICE *PciIoDevice,
718 IN UINT16 *Command,
719 IN UINT16 *BridgeControl,
720 IN UINT16 *OldCommand,
721 IN UINT16 *OldBridgeControl
722 )
723 /*++
724
725 Routine Description:
726
727 Arguments:
728
729 Returns:
730
731 None
732
733 --*/
734 // TODO: PciIoDevice - add argument and description to function comment
735 // TODO: Command - add argument and description to function comment
736 // TODO: BridgeControl - add argument and description to function comment
737 // TODO: OldCommand - add argument and description to function comment
738 // TODO: OldBridgeControl - add argument and description to function comment
739 // TODO: EFI_SUCCESS - add return value to function comment
740 {
741 EFI_TPL OldTpl;
742
743 //
744 // Preserve the original value
745 //
746 PciReadCommandRegister (PciIoDevice, OldCommand);
747
748 //
749 // Raise TPL to high level to disable timer interrupt while the BAR is probed
750 //
751 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
752
753 PciSetCommandRegister (PciIoDevice, *Command);
754 PciReadCommandRegister (PciIoDevice, Command);
755
756 //
757 // Write back the original value
758 //
759 PciSetCommandRegister (PciIoDevice, *OldCommand);
760
761 //
762 // Restore TPL to its original level
763 //
764 gBS->RestoreTPL (OldTpl);
765
766 if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
767
768 //
769 // Preserve the original value
770 //
771 PciReadBridgeControlRegister (PciIoDevice, OldBridgeControl);
772
773 //
774 // Raise TPL to high level to disable timer interrupt while the BAR is probed
775 //
776 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
777
778 PciSetBridgeControlRegister (PciIoDevice, *BridgeControl);
779 PciReadBridgeControlRegister (PciIoDevice, BridgeControl);
780
781 //
782 // Write back the original value
783 //
784 PciSetBridgeControlRegister (PciIoDevice, *OldBridgeControl);
785
786 //
787 // Restore TPL to its original level
788 //
789 gBS->RestoreTPL (OldTpl);
790
791 } else {
792 *OldBridgeControl = 0;
793 *BridgeControl = 0;
794 }
795
796 return EFI_SUCCESS;
797 }
798
799 EFI_STATUS
800 PciSetDeviceAttribute (
801 IN PCI_IO_DEVICE *PciIoDevice,
802 IN UINT16 Command,
803 IN UINT16 BridgeControl,
804 IN UINTN Option
805 )
806 /*++
807
808 Routine Description:
809 Set the supported or current attributes of a PCI device
810
811 Arguments:
812 PciIoDevice - Structure pointer for PCI device.
813 Command - Command register value.
814 BridgeControl - Bridge control value for PPB or P2C.
815 Option - Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.
816
817 Returns:
818
819 --*/
820
821 /*++
822
823 Routine Description:
824
825
826
827 Arguments:
828
829
830 Returns:
831
832 EFI_SUCCESS Always success
833
834
835 --*/
836 {
837 UINT64 Attributes;
838
839 Attributes = 0;
840
841 if (Command & EFI_PCI_COMMAND_IO_SPACE) {
842 Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;
843 }
844
845 if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) {
846 Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;
847 }
848
849 if (Command & EFI_PCI_COMMAND_BUS_MASTER) {
850 Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
851 }
852
853 if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {
854 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
855 }
856
857 if (BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) {
858 Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
859 }
860
861 if (BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) {
862 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
863 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
864 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
865 }
866
867 if (BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16) {
868 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16;
869 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16;
870 }
871
872 if (Option == EFI_SET_SUPPORTS) {
873
874 Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE |
875 EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED |
876 EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE |
877 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |
878 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM |
879 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
880
881 if (Attributes & EFI_PCI_IO_ATTRIBUTE_IO) {
882 Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;
883 Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
884 }
885
886 if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
887 //
888 // For bridge, it should support IDE attributes
889 //
890 Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;
891 Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;
892 } else {
893
894 if (IS_PCI_IDE (&PciIoDevice->Pci)) {
895 Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;
896 Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;
897 }
898
899 if (IS_PCI_VGA (&PciIoDevice->Pci)) {
900 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
901 Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
902 }
903 }
904
905 PciIoDevice->Supports = Attributes;
906 PciIoDevice->Supports &= ( (PciIoDevice->Parent->Supports) | \
907 EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | \
908 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER );
909
910 } else {
911 PciIoDevice->Attributes = Attributes;
912 }
913
914 return EFI_SUCCESS;
915 }
916
917 EFI_STATUS
918 GetFastBackToBackSupport (
919 IN PCI_IO_DEVICE *PciIoDevice,
920 IN UINT8 StatusIndex
921 )
922 /*++
923
924 Routine Description:
925
926 Determine if the device can support Fast Back to Back attribute
927
928 Arguments:
929
930 Returns:
931
932 None
933
934 --*/
935 // TODO: PciIoDevice - add argument and description to function comment
936 // TODO: StatusIndex - add argument and description to function comment
937 // TODO: EFI_UNSUPPORTED - add return value to function comment
938 // TODO: EFI_SUCCESS - add return value to function comment
939 // TODO: EFI_UNSUPPORTED - add return value to function comment
940 {
941 EFI_PCI_IO_PROTOCOL *PciIo;
942 EFI_STATUS Status;
943 UINT32 StatusRegister;
944
945 //
946 // Read the status register
947 //
948 PciIo = &PciIoDevice->PciIo;
949 Status = PciIoRead (PciIo, EfiPciIoWidthUint16, StatusIndex, 1, &StatusRegister);
950 if (EFI_ERROR (Status)) {
951 return EFI_UNSUPPORTED;
952 }
953
954 //
955 // Check the Fast B2B bit
956 //
957 if (StatusRegister & EFI_PCI_FAST_BACK_TO_BACK_CAPABLE) {
958 return EFI_SUCCESS;
959 } else {
960 return EFI_UNSUPPORTED;
961 }
962
963 }
964
965 STATIC
966 EFI_STATUS
967 ProcessOptionRomLight (
968 IN PCI_IO_DEVICE *PciIoDevice
969 )
970 /*++
971
972 Routine Description:
973
974 Process the option ROM for all the children of the specified parent PCI device.
975 It can only be used after the first full Option ROM process.
976
977 Arguments:
978
979 Returns:
980
981 None
982
983 --*/
984 // TODO: PciIoDevice - add argument and description to function comment
985 // TODO: EFI_SUCCESS - add return value to function comment
986 {
987 PCI_IO_DEVICE *Temp;
988 LIST_ENTRY *CurrentLink;
989
990 //
991 // For RootBridge, PPB , P2C, go recursively to traverse all its children
992 //
993 CurrentLink = PciIoDevice->ChildList.ForwardLink;
994 while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {
995
996 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
997
998 if (!IsListEmpty (&Temp->ChildList)) {
999 ProcessOptionRomLight (Temp);
1000 }
1001
1002 PciRomGetImageMapping (Temp);
1003
1004 //
1005 // The OpRom has already been processed in the first round
1006 //
1007 Temp->AllOpRomProcessed = TRUE;
1008
1009 CurrentLink = CurrentLink->ForwardLink;
1010 }
1011
1012 return EFI_SUCCESS;
1013 }
1014
1015 EFI_STATUS
1016 DetermineDeviceAttribute (
1017 IN PCI_IO_DEVICE *PciIoDevice
1018 )
1019 /*++
1020
1021 Routine Description:
1022
1023 Determine the related attributes of all devices under a Root Bridge
1024
1025 Arguments:
1026
1027 Returns:
1028
1029 None
1030
1031 --*/
1032 // TODO: PciIoDevice - add argument and description to function comment
1033 // TODO: EFI_SUCCESS - add return value to function comment
1034 {
1035 UINT16 Command;
1036 UINT16 BridgeControl;
1037 UINT16 OldCommand;
1038 UINT16 OldBridgeControl;
1039 BOOLEAN FastB2BSupport;
1040
1041 /*
1042 UINT8 IdePI;
1043 EFI_PCI_IO_PROTOCOL *PciIo;
1044 */
1045 PCI_IO_DEVICE *Temp;
1046 LIST_ENTRY *CurrentLink;
1047 EFI_STATUS Status;
1048
1049 //
1050 // For Root Bridge, just copy it by RootBridgeIo proctocol
1051 // so as to keep consistent with the actual attribute
1052 //
1053 if (!PciIoDevice->Parent) {
1054 Status = PciIoDevice->PciRootBridgeIo->GetAttributes (
1055 PciIoDevice->PciRootBridgeIo,
1056 &PciIoDevice->Supports,
1057 &PciIoDevice->Attributes
1058 );
1059 if (EFI_ERROR (Status)) {
1060 return Status;
1061 }
1062 } else {
1063
1064 //
1065 // Set the attributes to be checked for common PCI devices and PPB or P2C
1066 // Since some devices only support part of them, it is better to set the
1067 // attribute according to its command or bridge control register
1068 //
1069 Command = EFI_PCI_COMMAND_IO_SPACE |
1070 EFI_PCI_COMMAND_MEMORY_SPACE |
1071 EFI_PCI_COMMAND_BUS_MASTER |
1072 EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
1073
1074 BridgeControl = EFI_PCI_BRIDGE_CONTROL_ISA | EFI_PCI_BRIDGE_CONTROL_VGA | EFI_PCI_BRIDGE_CONTROL_VGA_16;
1075
1076 //
1077 // Test whether the device can support attributes above
1078 //
1079 PciTestSupportedAttribute (PciIoDevice, &Command, &BridgeControl, &OldCommand, &OldBridgeControl);
1080
1081 //
1082 // Set the supported attributes for specified PCI device
1083 //
1084 PciSetDeviceAttribute (PciIoDevice, Command, BridgeControl, EFI_SET_SUPPORTS);
1085
1086 //
1087 // Set the current attributes for specified PCI device
1088 //
1089 PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES);
1090
1091 //
1092 // Enable other supported attributes but not defined in PCI_IO_PROTOCOL
1093 //
1094 PciEnableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);
1095
1096 //
1097 // Enable IDE native mode
1098 //
1099 /*
1100 if (IS_PCI_IDE(&PciIoDevice->Pci)) {
1101
1102 PciIo = &PciIoDevice->PciIo;
1103
1104 PciIoRead (
1105 PciIo,
1106 EfiPciIoWidthUint8,
1107 0x09,
1108 1,
1109 &IdePI
1110 );
1111
1112 //
1113 // Set native mode if it can be supported
1114 //
1115 IdePI |= (((IdePI & 0x0F) >> 1) & 0x05);
1116
1117 PciIoWrite (
1118 PciIo,
1119 EfiPciIoWidthUint8,
1120 0x09,
1121 1,
1122 &IdePI
1123 );
1124
1125 }
1126 */
1127 }
1128
1129 FastB2BSupport = TRUE;
1130
1131 //
1132 // P2C can not support FB2B on the secondary side
1133 //
1134 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
1135 FastB2BSupport = FALSE;
1136 }
1137
1138 //
1139 // For RootBridge, PPB , P2C, go recursively to traverse all its children
1140 //
1141 CurrentLink = PciIoDevice->ChildList.ForwardLink;
1142 while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {
1143
1144 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
1145 Status = DetermineDeviceAttribute (Temp);
1146 if (EFI_ERROR (Status)) {
1147 return Status;
1148 }
1149 //
1150 // Detect Fast Bact to Bact support for the device under the bridge
1151 //
1152 Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET);
1153 if (FastB2BSupport && EFI_ERROR (Status)) {
1154 FastB2BSupport = FALSE;
1155 }
1156
1157 CurrentLink = CurrentLink->ForwardLink;
1158 }
1159 //
1160 // Set or clear Fast Back to Back bit for the whole bridge
1161 //
1162 if (!IsListEmpty (&PciIoDevice->ChildList)) {
1163
1164 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
1165
1166 Status = GetFastBackToBackSupport (PciIoDevice, PCI_BRIDGE_STATUS_REGISTER_OFFSET);
1167
1168 if (EFI_ERROR (Status) || (!FastB2BSupport)) {
1169 FastB2BSupport = FALSE;
1170 PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);
1171 } else {
1172 PciEnableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);
1173 }
1174 }
1175
1176 CurrentLink = PciIoDevice->ChildList.ForwardLink;
1177 while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {
1178 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
1179 if (FastB2BSupport) {
1180 PciEnableCommandRegister (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);
1181 } else {
1182 PciDisableCommandRegister (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);
1183 }
1184
1185 CurrentLink = CurrentLink->ForwardLink;
1186 }
1187 }
1188 //
1189 // End for IsListEmpty
1190 //
1191 return EFI_SUCCESS;
1192 }
1193
1194 EFI_STATUS
1195 UpdatePciInfo (
1196 IN PCI_IO_DEVICE *PciIoDevice
1197 )
1198 /*++
1199
1200 Routine Description:
1201
1202 This routine is used to update the bar information for those incompatible PCI device
1203
1204 Arguments:
1205
1206 Returns:
1207
1208 None
1209
1210 --*/
1211 // TODO: PciIoDevice - add argument and description to function comment
1212 // TODO: EFI_UNSUPPORTED - add return value to function comment
1213 {
1214 EFI_STATUS Status;
1215 UINTN BarIndex;
1216 UINTN BarEndIndex;
1217 BOOLEAN SetFlag;
1218 EFI_PCI_DEVICE_INFO PciDeviceInfo;
1219 VOID *Configuration;
1220 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
1221
1222 Configuration = NULL;
1223 Status = EFI_SUCCESS;
1224
1225 if (gEfiIncompatiblePciDeviceSupport == NULL) {
1226 //
1227 // It can only be supported after the Incompatible PCI Device
1228 // Support Protocol has been installed
1229 //
1230 Status = gBS->LocateProtocol (
1231 &gEfiIncompatiblePciDeviceSupportProtocolGuid,
1232 NULL,
1233 (VOID **) &gEfiIncompatiblePciDeviceSupport
1234 );
1235 }
1236 if (Status == EFI_SUCCESS) {
1237 //
1238 // Check whether the device belongs to incompatible devices from protocol or not
1239 // If it is , then get its special requirement in the ACPI table
1240 //
1241 Status = gEfiIncompatiblePciDeviceSupport->CheckDevice (
1242 gEfiIncompatiblePciDeviceSupport,
1243 PciIoDevice->Pci.Hdr.VendorId,
1244 PciIoDevice->Pci.Hdr.DeviceId,
1245 PciIoDevice->Pci.Hdr.RevisionID,
1246 PciIoDevice->Pci.Device.SubsystemVendorID,
1247 PciIoDevice->Pci.Device.SubsystemID,
1248 &Configuration
1249 );
1250
1251 }
1252
1253 if (EFI_ERROR (Status)) {
1254 //
1255 // Check whether the device belongs to incompatible devices from library or not
1256 // If it is , then get its special requirement in the ACPI table
1257 //
1258 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_ACPI_RESOURCE_SUPPORT) {
1259 PciDeviceInfo.VendorID = PciIoDevice->Pci.Hdr.VendorId;
1260 PciDeviceInfo.DeviceID = PciIoDevice->Pci.Hdr.DeviceId;
1261 PciDeviceInfo.RevisionID = PciIoDevice->Pci.Hdr.RevisionID;
1262 PciDeviceInfo.SubsystemVendorID = PciIoDevice->Pci.Device.SubsystemVendorID;
1263 PciDeviceInfo.SubsystemID = PciIoDevice->Pci.Device.SubsystemID;
1264
1265 Status = PciResourceUpdateCheck (&PciDeviceInfo, &Configuration);
1266 }
1267 }
1268
1269 if (EFI_ERROR (Status)) {
1270 return EFI_UNSUPPORTED;
1271 }
1272
1273 //
1274 // Update PCI device information from the ACPI table
1275 //
1276 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
1277
1278 while (Ptr->Desc != ACPI_END_TAG_DESCRIPTOR) {
1279
1280 if (Ptr->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
1281 //
1282 // The format is not support
1283 //
1284 break;
1285 }
1286
1287 BarIndex = (UINTN) Ptr->AddrTranslationOffset;
1288 BarEndIndex = BarIndex;
1289
1290 //
1291 // Update all the bars in the device
1292 //
1293 if (BarIndex == PCI_BAR_ALL) {
1294 BarIndex = 0;
1295 BarEndIndex = PCI_MAX_BAR - 1;
1296 }
1297
1298 if (BarIndex >= PCI_MAX_BAR) {
1299 Ptr++;
1300 continue;
1301 }
1302
1303 for (; BarIndex <= BarEndIndex; BarIndex++) {
1304 SetFlag = FALSE;
1305 switch (Ptr->ResType) {
1306 case ACPI_ADDRESS_SPACE_TYPE_MEM:
1307
1308 //
1309 // Make sure the bar is memory type
1310 //
1311 if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem)) {
1312 SetFlag = TRUE;
1313 }
1314 break;
1315
1316 case ACPI_ADDRESS_SPACE_TYPE_IO:
1317
1318 //
1319 // Make sure the bar is IO type
1320 //
1321 if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeIo)) {
1322 SetFlag = TRUE;
1323 }
1324 break;
1325 }
1326
1327 if (SetFlag) {
1328
1329 //
1330 // Update the new alignment for the device
1331 //
1332 SetNewAlign (&(PciIoDevice->PciBar[BarIndex].Alignment), Ptr->AddrRangeMax);
1333
1334 //
1335 // Update the new length for the device
1336 //
1337 if (Ptr->AddrLen != PCI_BAR_NOCHANGE) {
1338 PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen;
1339 }
1340 }
1341 }
1342
1343 Ptr++;
1344 }
1345
1346 gBS->FreePool (Configuration);
1347 return Status;
1348
1349 }
1350
1351 VOID
1352 SetNewAlign (
1353 IN UINT64 *Alignment,
1354 IN UINT64 NewAlignment
1355 )
1356 /*++
1357
1358 Routine Description:
1359
1360 This routine will update the alignment with the new alignment
1361
1362 Arguments:
1363
1364 Returns:
1365
1366 None
1367
1368 --*/
1369 // TODO: Alignment - add argument and description to function comment
1370 // TODO: NewAlignment - add argument and description to function comment
1371 {
1372 UINT64 OldAlignment;
1373 UINTN ShiftBit;
1374
1375 //
1376 // The new alignment is the same as the original,
1377 // so skip it
1378 //
1379 if (NewAlignment == PCI_BAR_OLD_ALIGN) {
1380 return ;
1381 }
1382 //
1383 // Check the validity of the parameter
1384 //
1385 if (NewAlignment != PCI_BAR_EVEN_ALIGN &&
1386 NewAlignment != PCI_BAR_SQUAD_ALIGN &&
1387 NewAlignment != PCI_BAR_DQUAD_ALIGN ) {
1388 *Alignment = NewAlignment;
1389 return ;
1390 }
1391
1392 OldAlignment = (*Alignment) + 1;
1393 ShiftBit = 0;
1394
1395 //
1396 // Get the first non-zero hex value of the length
1397 //
1398 while ((OldAlignment & 0x0F) == 0x00) {
1399 OldAlignment = RShiftU64 (OldAlignment, 4);
1400 ShiftBit += 4;
1401 }
1402
1403 //
1404 // Adjust the alignment to even, quad or double quad boundary
1405 //
1406 if (NewAlignment == PCI_BAR_EVEN_ALIGN) {
1407 if (OldAlignment & 0x01) {
1408 OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01);
1409 }
1410 } else if (NewAlignment == PCI_BAR_SQUAD_ALIGN) {
1411 if (OldAlignment & 0x03) {
1412 OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03);
1413 }
1414 } else if (NewAlignment == PCI_BAR_DQUAD_ALIGN) {
1415 if (OldAlignment & 0x07) {
1416 OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07);
1417 }
1418 }
1419
1420 //
1421 // Update the old value
1422 //
1423 NewAlignment = LShiftU64 (OldAlignment, ShiftBit) - 1;
1424 *Alignment = NewAlignment;
1425
1426 return ;
1427 }
1428
1429 UINTN
1430 PciParseBar (
1431 IN PCI_IO_DEVICE *PciIoDevice,
1432 IN UINTN Offset,
1433 IN UINTN BarIndex
1434 )
1435 /*++
1436
1437 Routine Description:
1438
1439 Arguments:
1440
1441 Returns:
1442
1443 None
1444
1445 --*/
1446 // TODO: PciIoDevice - add argument and description to function comment
1447 // TODO: Offset - add argument and description to function comment
1448 // TODO: BarIndex - add argument and description to function comment
1449 {
1450 UINT32 Value;
1451 UINT32 OriginalValue;
1452 UINT32 Mask;
1453 UINT32 Data;
1454 UINT8 Index;
1455 EFI_STATUS Status;
1456
1457 OriginalValue = 0;
1458 Value = 0;
1459
1460 Status = BarExisted (
1461 PciIoDevice,
1462 Offset,
1463 &Value,
1464 &OriginalValue
1465 );
1466
1467 if (EFI_ERROR (Status)) {
1468 PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
1469 PciIoDevice->PciBar[BarIndex].Length = 0;
1470 PciIoDevice->PciBar[BarIndex].Alignment = 0;
1471
1472 //
1473 // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
1474 //
1475 PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
1476 return Offset + 4;
1477 }
1478
1479 PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
1480 if (Value & 0x01) {
1481 //
1482 // Device I/Os
1483 //
1484 Mask = 0xfffffffc;
1485
1486 if (Value & 0xFFFF0000) {
1487 //
1488 // It is a IO32 bar
1489 //
1490 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo32;
1491 PciIoDevice->PciBar[BarIndex].Length = ((~(Value & Mask)) + 1);
1492 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1493
1494 } else {
1495 //
1496 // It is a IO16 bar
1497 //
1498 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo16;
1499 PciIoDevice->PciBar[BarIndex].Length = 0x0000FFFF & ((~(Value & Mask)) + 1);
1500 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1501
1502 }
1503 //
1504 // Workaround. Some platforms inplement IO bar with 0 length
1505 // Need to treat it as no-bar
1506 //
1507 if (PciIoDevice->PciBar[BarIndex].Length == 0) {
1508 PciIoDevice->PciBar[BarIndex].BarType = (PCI_BAR_TYPE) 0;
1509 }
1510
1511 PciIoDevice->PciBar[BarIndex].Prefetchable = FALSE;
1512 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
1513
1514 } else {
1515
1516 Mask = 0xfffffff0;
1517
1518 PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
1519
1520 switch (Value & 0x07) {
1521
1522 //
1523 //memory space; anywhere in 32 bit address space
1524 //
1525 case 0x00:
1526 if (Value & 0x08) {
1527 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
1528 } else {
1529 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
1530 }
1531
1532 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
1533 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1534
1535 break;
1536
1537 //
1538 // memory space; anywhere in 64 bit address space
1539 //
1540 case 0x04:
1541 if (Value & 0x08) {
1542 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;
1543 } else {
1544 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;
1545 }
1546
1547 //
1548 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1549 // is regarded as an extension for the first bar. As a result
1550 // the sizing will be conducted on combined 64 bit value
1551 // Here just store the masked first 32bit value for future size
1552 // calculation
1553 //
1554 PciIoDevice->PciBar[BarIndex].Length = Value & Mask;
1555 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1556
1557 //
1558 // Increment the offset to point to next DWORD
1559 //
1560 Offset += 4;
1561
1562 Status = BarExisted (
1563 PciIoDevice,
1564 Offset,
1565 &Value,
1566 &OriginalValue
1567 );
1568
1569 if (EFI_ERROR (Status)) {
1570 return Offset + 4;
1571 }
1572
1573 //
1574 // Fix the length to support some spefic 64 bit BAR
1575 //
1576 Data = Value;
1577 Index = 0;
1578 for (Data = Value; Data != 0; Data >>= 1) {
1579 Index ++;
1580 }
1581 Value |= ((UINT32)(-1) << Index);
1582
1583 //
1584 // Calculate the size of 64bit bar
1585 //
1586 PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);
1587
1588 PciIoDevice->PciBar[BarIndex].Length = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);
1589 PciIoDevice->PciBar[BarIndex].Length = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;
1590 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1591
1592 break;
1593
1594 //
1595 // reserved
1596 //
1597 default:
1598 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
1599 PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
1600 PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
1601
1602 break;
1603 }
1604 }
1605
1606 //
1607 // Check the length again so as to keep compatible with some special bars
1608 //
1609 if (PciIoDevice->PciBar[BarIndex].Length == 0) {
1610 PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
1611 PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
1612 PciIoDevice->PciBar[BarIndex].Alignment = 0;
1613 }
1614
1615 //
1616 // Increment number of bar
1617 //
1618 return Offset + 4;
1619 }
1620
1621 EFI_STATUS
1622 InitializePciDevice (
1623 IN PCI_IO_DEVICE *PciIoDevice
1624 )
1625 /*++
1626
1627 Routine Description:
1628
1629 This routine is used to initialize the bar of a PCI device
1630 It can be called typically when a device is going to be rejected
1631
1632 Arguments:
1633
1634 Returns:
1635
1636 None
1637
1638 --*/
1639 // TODO: PciIoDevice - add argument and description to function comment
1640 // TODO: EFI_SUCCESS - add return value to function comment
1641 {
1642 EFI_PCI_IO_PROTOCOL *PciIo;
1643 UINT8 Offset;
1644
1645 PciIo = &(PciIoDevice->PciIo);
1646
1647 //
1648 // Put all the resource apertures
1649 // Resource base is set to all ones so as to indicate its resource
1650 // has not been alloacted
1651 //
1652 for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {
1653 PciIoWrite (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne);
1654 }
1655
1656 return EFI_SUCCESS;
1657 }
1658
1659 EFI_STATUS
1660 InitializePpb (
1661 IN PCI_IO_DEVICE *PciIoDevice
1662 )
1663 /*++
1664
1665 Routine Description:
1666
1667 Arguments:
1668
1669 Returns:
1670
1671 None
1672
1673 --*/
1674 // TODO: PciIoDevice - add argument and description to function comment
1675 // TODO: EFI_SUCCESS - add return value to function comment
1676 {
1677 EFI_PCI_IO_PROTOCOL *PciIo;
1678
1679 PciIo = &(PciIoDevice->PciIo);
1680
1681 //
1682 // Put all the resource apertures including IO16
1683 // Io32, pMem32, pMem64 to quiescent state
1684 // Resource base all ones, Resource limit all zeros
1685 //
1686 PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
1687 PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);
1688
1689 PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);
1690 PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);
1691
1692 PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);
1693 PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);
1694
1695 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);
1696 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);
1697
1698 //
1699 // don't support use io32 as for now
1700 //
1701 PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);
1702 PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);
1703
1704 //
1705 // Force Interrupt line to zero for cards that come up randomly
1706 //
1707 PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
1708
1709 return EFI_SUCCESS;
1710 }
1711
1712 EFI_STATUS
1713 InitializeP2C (
1714 IN PCI_IO_DEVICE *PciIoDevice
1715 )
1716 /*++
1717
1718 Routine Description:
1719
1720 Arguments:
1721
1722 Returns:
1723
1724 None
1725
1726 --*/
1727 // TODO: PciIoDevice - add argument and description to function comment
1728 // TODO: EFI_SUCCESS - add return value to function comment
1729 {
1730 EFI_PCI_IO_PROTOCOL *PciIo;
1731
1732 PciIo = &(PciIoDevice->PciIo);
1733
1734 //
1735 // Put all the resource apertures including IO16
1736 // Io32, pMem32, pMem64 to quiescent state(
1737 // Resource base all ones, Resource limit all zeros
1738 //
1739 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);
1740 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);
1741
1742 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);
1743 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);
1744
1745 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);
1746 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);
1747
1748 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);
1749 PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);
1750
1751 //
1752 // Force Interrupt line to zero for cards that come up randomly
1753 //
1754 PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
1755 return EFI_SUCCESS;
1756 }
1757
1758 PCI_IO_DEVICE *
1759 CreatePciIoDevice (
1760 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
1761 IN PCI_TYPE00 *Pci,
1762 UINT8 Bus,
1763 UINT8 Device,
1764 UINT8 Func
1765 )
1766 /*++
1767
1768 Routine Description:
1769
1770 Arguments:
1771
1772 Returns:
1773
1774 None
1775
1776 --*/
1777 // TODO: PciRootBridgeIo - add argument and description to function comment
1778 // TODO: Pci - add argument and description to function comment
1779 // TODO: Bus - add argument and description to function comment
1780 // TODO: Device - add argument and description to function comment
1781 // TODO: Func - add argument and description to function comment
1782 {
1783
1784 EFI_STATUS Status;
1785 PCI_IO_DEVICE *PciIoDevice;
1786
1787 PciIoDevice = NULL;
1788
1789 Status = gBS->AllocatePool (
1790 EfiBootServicesData,
1791 sizeof (PCI_IO_DEVICE),
1792 (VOID **) &PciIoDevice
1793 );
1794
1795 if (EFI_ERROR (Status)) {
1796 return NULL;
1797 }
1798
1799 ZeroMem (PciIoDevice, sizeof (PCI_IO_DEVICE));
1800
1801 PciIoDevice->Signature = PCI_IO_DEVICE_SIGNATURE;
1802 PciIoDevice->Handle = NULL;
1803 PciIoDevice->PciRootBridgeIo = PciRootBridgeIo;
1804 PciIoDevice->DevicePath = NULL;
1805 PciIoDevice->BusNumber = Bus;
1806 PciIoDevice->DeviceNumber = Device;
1807 PciIoDevice->FunctionNumber = Func;
1808 PciIoDevice->Decodes = 0;
1809 if (gFullEnumeration) {
1810 PciIoDevice->Allocated = FALSE;
1811 } else {
1812 PciIoDevice->Allocated = TRUE;
1813 }
1814
1815 PciIoDevice->Registered = FALSE;
1816 PciIoDevice->Attributes = 0;
1817 PciIoDevice->Supports = 0;
1818 PciIoDevice->BusOverride = FALSE;
1819 PciIoDevice->AllOpRomProcessed = FALSE;
1820
1821 PciIoDevice->IsPciExp = FALSE;
1822
1823 CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));
1824
1825 //
1826 // Initialize the PCI I/O instance structure
1827 //
1828
1829 Status = InitializePciIoInstance (PciIoDevice);
1830 Status = InitializePciDriverOverrideInstance (PciIoDevice);
1831
1832 if (EFI_ERROR (Status)) {
1833 gBS->FreePool (PciIoDevice);
1834 return NULL;
1835 }
1836
1837 //
1838 // Initialize the reserved resource list
1839 //
1840 InitializeListHead (&PciIoDevice->ReservedResourceList);
1841
1842 //
1843 // Initialize the driver list
1844 //
1845 InitializeListHead (&PciIoDevice->OptionRomDriverList);
1846
1847 //
1848 // Initialize the child list
1849 //
1850 InitializeListHead (&PciIoDevice->ChildList);
1851
1852 return PciIoDevice;
1853 }
1854
1855 EFI_STATUS
1856 PciEnumeratorLight (
1857 IN EFI_HANDLE Controller
1858 )
1859 /*++
1860
1861 Routine Description:
1862
1863 This routine is used to enumerate entire pci bus system
1864 in a given platform
1865 It is only called on the second start on the same Root Bridge.
1866
1867 Arguments:
1868
1869 Returns:
1870
1871 None
1872
1873 --*/
1874 // TODO: Controller - add argument and description to function comment
1875 // TODO: EFI_SUCCESS - add return value to function comment
1876 // TODO: EFI_SUCCESS - add return value to function comment
1877 {
1878
1879 EFI_STATUS Status;
1880 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1881 PCI_IO_DEVICE *RootBridgeDev;
1882 UINT16 MinBus;
1883 UINT16 MaxBus;
1884 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
1885
1886 MinBus = 0;
1887 MaxBus = PCI_MAX_BUS;
1888 Descriptors = NULL;
1889
1890 //
1891 // If this root bridge has been already enumerated, then return successfully
1892 //
1893 if (GetRootBridgeByHandle (Controller) != NULL) {
1894 return EFI_SUCCESS;
1895 }
1896
1897 //
1898 // Open pci root bridge io protocol
1899 //
1900 Status = gBS->OpenProtocol (
1901 Controller,
1902 &gEfiPciRootBridgeIoProtocolGuid,
1903 (VOID **) &PciRootBridgeIo,
1904 gPciBusDriverBinding.DriverBindingHandle,
1905 Controller,
1906 EFI_OPEN_PROTOCOL_BY_DRIVER
1907 );
1908 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
1909 return Status;
1910 }
1911
1912 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
1913
1914 if (EFI_ERROR (Status)) {
1915 return Status;
1916 }
1917
1918 while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {
1919
1920 //
1921 // Create a device node for root bridge device with a NULL host bridge controller handle
1922 //
1923 RootBridgeDev = CreateRootBridge (Controller);
1924
1925 if (!RootBridgeDev) {
1926 Descriptors++;
1927 continue;
1928 }
1929
1930 //
1931 // Record the root bridge io protocol
1932 //
1933 RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
1934
1935 Status = PciPciDeviceInfoCollector (
1936 RootBridgeDev,
1937 (UINT8) MinBus
1938 );
1939
1940 if (!EFI_ERROR (Status)) {
1941
1942 //
1943 // Remove those PCI devices which are rejected when full enumeration
1944 //
1945 RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev);
1946
1947 //
1948 // Process option rom light
1949 //
1950 ProcessOptionRomLight (RootBridgeDev);
1951
1952 //
1953 // Determine attributes for all devices under this root bridge
1954 //
1955 DetermineDeviceAttribute (RootBridgeDev);
1956
1957 //
1958 // If successfully, insert the node into device pool
1959 //
1960 InsertRootBridge (RootBridgeDev);
1961 } else {
1962
1963 //
1964 // If unsuccessly, destroy the entire node
1965 //
1966 DestroyRootBridge (RootBridgeDev);
1967 }
1968
1969 Descriptors++;
1970 }
1971
1972 return EFI_SUCCESS;
1973 }
1974
1975 EFI_STATUS
1976 PciGetBusRange (
1977 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
1978 OUT UINT16 *MinBus,
1979 OUT UINT16 *MaxBus,
1980 OUT UINT16 *BusRange
1981 )
1982 /*++
1983
1984 Routine Description:
1985
1986 Get the bus range.
1987
1988 Arguments:
1989
1990 Descriptors - A pointer to the address space descriptor.
1991 MinBus - The min bus.
1992 MaxBus - The max bus.
1993 BusRange - The bus range.
1994
1995 Returns:
1996
1997 Status Code.
1998
1999 --*/
2000 // TODO: EFI_SUCCESS - add return value to function comment
2001 // TODO: EFI_NOT_FOUND - add return value to function comment
2002 {
2003
2004 while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {
2005 if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
2006 if (MinBus != NULL) {
2007 *MinBus = (UINT16) (*Descriptors)->AddrRangeMin;
2008 }
2009
2010 if (MaxBus != NULL) {
2011 *MaxBus = (UINT16) (*Descriptors)->AddrRangeMax;
2012 }
2013
2014 if (BusRange != NULL) {
2015 *BusRange = (UINT16) (*Descriptors)->AddrLen;
2016 }
2017
2018 return EFI_SUCCESS;
2019 }
2020
2021 (*Descriptors)++;
2022 }
2023
2024 return EFI_NOT_FOUND;
2025 }
2026
2027 EFI_STATUS
2028 StartManagingRootBridge (
2029 IN PCI_IO_DEVICE *RootBridgeDev
2030 )
2031 /*++
2032
2033 Routine Description:
2034
2035
2036 Arguments:
2037
2038 Returns:
2039
2040 None
2041
2042 --*/
2043 // TODO: RootBridgeDev - add argument and description to function comment
2044 // TODO: EFI_SUCCESS - add return value to function comment
2045 {
2046 EFI_HANDLE RootBridgeHandle;
2047 EFI_STATUS Status;
2048 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
2049
2050 //
2051 // Get the root bridge handle
2052 //
2053 RootBridgeHandle = RootBridgeDev->Handle;
2054 PciRootBridgeIo = NULL;
2055
2056 //
2057 // Get the pci root bridge io protocol
2058 //
2059 Status = gBS->OpenProtocol (
2060 RootBridgeHandle,
2061 &gEfiPciRootBridgeIoProtocolGuid,
2062 (VOID **) &PciRootBridgeIo,
2063 gPciBusDriverBinding.DriverBindingHandle,
2064 RootBridgeHandle,
2065 EFI_OPEN_PROTOCOL_BY_DRIVER
2066 );
2067
2068 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
2069 return Status;
2070 }
2071
2072 //
2073 // Store the PciRootBridgeIo protocol into root bridge private data
2074 //
2075 RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
2076
2077 return EFI_SUCCESS;
2078
2079 }
2080
2081 BOOLEAN
2082 IsPciDeviceRejected (
2083 IN PCI_IO_DEVICE *PciIoDevice
2084 )
2085 /*++
2086
2087 Routine Description:
2088
2089 This routine can be used to check whether a PCI device should be rejected when light enumeration
2090
2091 Arguments:
2092
2093 Returns:
2094
2095 TRUE This device should be rejected
2096 FALSE This device shouldn't be rejected
2097
2098 --*/
2099 // TODO: PciIoDevice - add argument and description to function comment
2100 {
2101 EFI_STATUS Status;
2102 UINT32 TestValue;
2103 UINT32 OldValue;
2104 UINT32 Mask;
2105 UINT8 BarOffset;
2106
2107 //
2108 // PPB should be skip!
2109 //
2110 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
2111 return FALSE;
2112 }
2113
2114 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
2115 //
2116 // Only test base registers for P2C
2117 //
2118 for (BarOffset = 0x1C; BarOffset <= 0x38; BarOffset += 2 * sizeof (UINT32)) {
2119
2120 Mask = (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;
2121 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
2122 if (EFI_ERROR (Status)) {
2123 continue;
2124 }
2125
2126 TestValue = TestValue & Mask;
2127 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
2128 //
2129 // The bar isn't programed, so it should be rejected
2130 //
2131 return TRUE;
2132 }
2133 }
2134
2135 return FALSE;
2136 }
2137
2138 for (BarOffset = 0x14; BarOffset <= 0x24; BarOffset += sizeof (UINT32)) {
2139 //
2140 // Test PCI devices
2141 //
2142 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
2143 if (EFI_ERROR (Status)) {
2144 continue;
2145 }
2146
2147 if (TestValue & 0x01) {
2148
2149 //
2150 // IO Bar
2151 //
2152
2153 Mask = 0xFFFFFFFC;
2154 TestValue = TestValue & Mask;
2155 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
2156 return TRUE;
2157 }
2158
2159 } else {
2160
2161 //
2162 // Mem Bar
2163 //
2164
2165 Mask = 0xFFFFFFF0;
2166 TestValue = TestValue & Mask;
2167
2168 if ((TestValue & 0x07) == 0x04) {
2169
2170 //
2171 // Mem64 or PMem64
2172 //
2173 BarOffset += sizeof (UINT32);
2174 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
2175
2176 //
2177 // Test its high 32-Bit BAR
2178 //
2179
2180 Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
2181 if (TestValue == OldValue) {
2182 return TRUE;
2183 }
2184 }
2185
2186 } else {
2187
2188 //
2189 // Mem32 or PMem32
2190 //
2191 if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
2192 return TRUE;
2193 }
2194 }
2195 }
2196 }
2197
2198 return FALSE;
2199 }
2200
2201 EFI_STATUS
2202 ResetAllPpbBusNumber (
2203 IN PCI_IO_DEVICE *Bridge,
2204 IN UINT8 StartBusNumber
2205 )
2206 /*++
2207
2208 Routine Description:
2209
2210 TODO: Add function description
2211
2212 Arguments:
2213
2214 Bridge - TODO: add argument description
2215 StartBusNumber - TODO: add argument description
2216
2217 Returns:
2218
2219 EFI_SUCCESS - TODO: Add description for return value
2220
2221 --*/
2222 {
2223 EFI_STATUS Status;
2224 PCI_TYPE00 Pci;
2225 UINT8 Device;
2226 UINT32 Register;
2227 UINT8 Func;
2228 UINT64 Address;
2229 UINT8 SecondaryBus;
2230 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
2231
2232 PciRootBridgeIo = Bridge->PciRootBridgeIo;
2233
2234 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
2235 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
2236
2237 //
2238 // Check to see whether a pci device is present
2239 //
2240 Status = PciDevicePresent (
2241 PciRootBridgeIo,
2242 &Pci,
2243 StartBusNumber,
2244 Device,
2245 Func
2246 );
2247
2248 if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) {
2249
2250 Register = 0;
2251 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
2252 Status = PciRootBridgeIoRead (
2253 PciRootBridgeIo,
2254 &Pci,
2255 EfiPciWidthUint32,
2256 Address,
2257 1,
2258 &Register
2259 );
2260 SecondaryBus = (UINT8)(Register >> 8);
2261
2262 if (SecondaryBus != 0) {
2263 ResetAllPpbBusNumber (Bridge, SecondaryBus);
2264 }
2265
2266 //
2267 // Reset register 18h, 19h, 1Ah on PCI Bridge
2268 //
2269 Register &= 0xFF000000;
2270 Status = PciRootBridgeIoWrite (
2271 PciRootBridgeIo,
2272 &Pci,
2273 EfiPciWidthUint32,
2274 Address,
2275 1,
2276 &Register
2277 );
2278 }
2279
2280 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
2281 //
2282 // Skip sub functions, this is not a multi function device
2283 //
2284 Func = PCI_MAX_FUNC;
2285 }
2286 }
2287 }
2288
2289 return EFI_SUCCESS;
2290 }
2291