1 /** @file
2   Main file for Pci shell Debug1 function.
3 
4   Copyright (c) 2005 - 2021, Intel Corporation. All rights reserved.<BR>
5   (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
6   (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
7   SPDX-License-Identifier: BSD-2-Clause-Patent
8 
9 **/
10 
11 #include "UefiShellDebug1CommandsLib.h"
12 #include <Protocol/PciRootBridgeIo.h>
13 #include <Library/ShellLib.h>
14 #include <IndustryStandard/Pci.h>
15 #include <IndustryStandard/Acpi.h>
16 #include "Pci.h"
17 
18 //
19 // Printable strings for Pci class code
20 //
21 typedef struct {
22   CHAR16  *BaseClass; // Pointer to the PCI base class string
23   CHAR16  *SubClass;  // Pointer to the PCI sub class string
24   CHAR16  *PIFClass;  // Pointer to the PCI programming interface string
25 } PCI_CLASS_STRINGS;
26 
27 //
28 // a structure holding a single entry, which also points to its lower level
29 // class
30 //
31 typedef struct PCI_CLASS_ENTRY_TAG {
32   UINT8                       Code;             // Class, subclass or I/F code
33   CHAR16                      *DescText;        // Description string
34   struct PCI_CLASS_ENTRY_TAG  *LowerLevelClass; // Subclass or I/F if any
35 } PCI_CLASS_ENTRY;
36 
37 //
38 // Declarations of entries which contain printable strings for class codes
39 // in PCI configuration space
40 //
41 PCI_CLASS_ENTRY PCIBlankEntry[];
42 PCI_CLASS_ENTRY PCISubClass_00[];
43 PCI_CLASS_ENTRY PCISubClass_01[];
44 PCI_CLASS_ENTRY PCISubClass_02[];
45 PCI_CLASS_ENTRY PCISubClass_03[];
46 PCI_CLASS_ENTRY PCISubClass_04[];
47 PCI_CLASS_ENTRY PCISubClass_05[];
48 PCI_CLASS_ENTRY PCISubClass_06[];
49 PCI_CLASS_ENTRY PCISubClass_07[];
50 PCI_CLASS_ENTRY PCISubClass_08[];
51 PCI_CLASS_ENTRY PCISubClass_09[];
52 PCI_CLASS_ENTRY PCISubClass_0a[];
53 PCI_CLASS_ENTRY PCISubClass_0b[];
54 PCI_CLASS_ENTRY PCISubClass_0c[];
55 PCI_CLASS_ENTRY PCISubClass_0d[];
56 PCI_CLASS_ENTRY PCISubClass_0e[];
57 PCI_CLASS_ENTRY PCISubClass_0f[];
58 PCI_CLASS_ENTRY PCISubClass_10[];
59 PCI_CLASS_ENTRY PCISubClass_11[];
60 PCI_CLASS_ENTRY PCISubClass_12[];
61 PCI_CLASS_ENTRY PCISubClass_13[];
62 PCI_CLASS_ENTRY PCIPIFClass_0100[];
63 PCI_CLASS_ENTRY PCIPIFClass_0101[];
64 PCI_CLASS_ENTRY PCIPIFClass_0105[];
65 PCI_CLASS_ENTRY PCIPIFClass_0106[];
66 PCI_CLASS_ENTRY PCIPIFClass_0107[];
67 PCI_CLASS_ENTRY PCIPIFClass_0108[];
68 PCI_CLASS_ENTRY PCIPIFClass_0109[];
69 PCI_CLASS_ENTRY PCIPIFClass_0300[];
70 PCI_CLASS_ENTRY PCIPIFClass_0604[];
71 PCI_CLASS_ENTRY PCIPIFClass_0609[];
72 PCI_CLASS_ENTRY PCIPIFClass_060b[];
73 PCI_CLASS_ENTRY PCIPIFClass_0700[];
74 PCI_CLASS_ENTRY PCIPIFClass_0701[];
75 PCI_CLASS_ENTRY PCIPIFClass_0703[];
76 PCI_CLASS_ENTRY PCIPIFClass_0800[];
77 PCI_CLASS_ENTRY PCIPIFClass_0801[];
78 PCI_CLASS_ENTRY PCIPIFClass_0802[];
79 PCI_CLASS_ENTRY PCIPIFClass_0803[];
80 PCI_CLASS_ENTRY PCIPIFClass_0904[];
81 PCI_CLASS_ENTRY PCIPIFClass_0c00[];
82 PCI_CLASS_ENTRY PCIPIFClass_0c03[];
83 PCI_CLASS_ENTRY PCIPIFClass_0c07[];
84 PCI_CLASS_ENTRY PCIPIFClass_0d01[];
85 PCI_CLASS_ENTRY PCIPIFClass_0e00[];
86 
87 //
88 // Base class strings entries
89 //
90 PCI_CLASS_ENTRY gClassStringList[] = {
91   {
92     0x00,
93     L"Pre 2.0 device",
94     PCISubClass_00
95   },
96   {
97     0x01,
98     L"Mass Storage Controller",
99     PCISubClass_01
100   },
101   {
102     0x02,
103     L"Network Controller",
104     PCISubClass_02
105   },
106   {
107     0x03,
108     L"Display Controller",
109     PCISubClass_03
110   },
111   {
112     0x04,
113     L"Multimedia Device",
114     PCISubClass_04
115   },
116   {
117     0x05,
118     L"Memory Controller",
119     PCISubClass_05
120   },
121   {
122     0x06,
123     L"Bridge Device",
124     PCISubClass_06
125   },
126   {
127     0x07,
128     L"Simple Communications Controllers",
129     PCISubClass_07
130   },
131   {
132     0x08,
133     L"Base System Peripherals",
134     PCISubClass_08
135   },
136   {
137     0x09,
138     L"Input Devices",
139     PCISubClass_09
140   },
141   {
142     0x0a,
143     L"Docking Stations",
144     PCISubClass_0a
145   },
146   {
147     0x0b,
148     L"Processors",
149     PCISubClass_0b
150   },
151   {
152     0x0c,
153     L"Serial Bus Controllers",
154     PCISubClass_0c
155   },
156   {
157     0x0d,
158     L"Wireless Controllers",
159     PCISubClass_0d
160   },
161   {
162     0x0e,
163     L"Intelligent IO Controllers",
164     PCISubClass_0e
165   },
166   {
167     0x0f,
168     L"Satellite Communications Controllers",
169     PCISubClass_0f
170   },
171   {
172     0x10,
173     L"Encryption/Decryption Controllers",
174     PCISubClass_10
175   },
176   {
177     0x11,
178     L"Data Acquisition & Signal Processing Controllers",
179     PCISubClass_11
180   },
181   {
182     0x12,
183     L"Processing Accelerators",
184     PCISubClass_12
185   },
186   {
187     0x13,
188     L"Non-Essential Instrumentation",
189     PCISubClass_13
190   },
191   {
192     0xff,
193     L"Device does not fit in any defined classes",
194     PCIBlankEntry
195   },
196   {
197     0x00,
198     NULL,
199     /* null string ends the list */NULL
200   }
201 };
202 
203 //
204 // Subclass strings entries
205 //
206 PCI_CLASS_ENTRY PCIBlankEntry[] = {
207   {
208     0x00,
209     L"",
210     PCIBlankEntry
211   },
212   {
213     0x00,
214     NULL,
215     /* null string ends the list */NULL
216   }
217 };
218 
219 PCI_CLASS_ENTRY PCISubClass_00[] = {
220   {
221     0x00,
222     L"All devices other than VGA",
223     PCIBlankEntry
224   },
225   {
226     0x01,
227     L"VGA-compatible devices",
228     PCIBlankEntry
229   },
230   {
231     0x00,
232     NULL,
233     /* null string ends the list */NULL
234   }
235 };
236 
237 PCI_CLASS_ENTRY PCISubClass_01[] = {
238   {
239     0x00,
240     L"SCSI",
241     PCIPIFClass_0100
242   },
243   {
244     0x01,
245     L"IDE controller",
246     PCIPIFClass_0101
247   },
248   {
249     0x02,
250     L"Floppy disk controller",
251     PCIBlankEntry
252   },
253   {
254     0x03,
255     L"IPI controller",
256     PCIBlankEntry
257   },
258   {
259     0x04,
260     L"RAID controller",
261     PCIBlankEntry
262   },
263   {
264     0x05,
265     L"ATA controller with ADMA interface",
266     PCIPIFClass_0105
267   },
268   {
269     0x06,
270     L"Serial ATA controller",
271     PCIPIFClass_0106
272   },
273   {
274     0x07,
275     L"Serial Attached SCSI (SAS) controller ",
276     PCIPIFClass_0107
277   },
278   {
279     0x08,
280     L"Non-volatile memory subsystem",
281     PCIPIFClass_0108
282   },
283   {
284     0x09,
285     L"Universal Flash Storage (UFS) controller ",
286     PCIPIFClass_0109
287   },
288   {
289     0x80,
290     L"Other mass storage controller",
291     PCIBlankEntry
292   },
293   {
294     0x00,
295     NULL,
296     /* null string ends the list */NULL
297   }
298 };
299 
300 PCI_CLASS_ENTRY PCISubClass_02[] = {
301   {
302     0x00,
303     L"Ethernet controller",
304     PCIBlankEntry
305   },
306   {
307     0x01,
308     L"Token ring controller",
309     PCIBlankEntry
310   },
311   {
312     0x02,
313     L"FDDI controller",
314     PCIBlankEntry
315   },
316   {
317     0x03,
318     L"ATM controller",
319     PCIBlankEntry
320   },
321   {
322     0x04,
323     L"ISDN controller",
324     PCIBlankEntry
325   },
326   {
327     0x05,
328     L"WorldFip controller",
329     PCIBlankEntry
330   },
331   {
332     0x06,
333     L"PICMG 2.14 Multi Computing",
334     PCIBlankEntry
335   },
336   {
337     0x07,
338     L"InfiniBand controller",
339     PCIBlankEntry
340   },
341   {
342     0x80,
343     L"Other network controller",
344     PCIBlankEntry
345   },
346   {
347     0x00,
348     NULL,
349     /* null string ends the list */NULL
350   }
351 };
352 
353 PCI_CLASS_ENTRY PCISubClass_03[] = {
354   {
355     0x00,
356     L"VGA/8514 controller",
357     PCIPIFClass_0300
358   },
359   {
360     0x01,
361     L"XGA controller",
362     PCIBlankEntry
363   },
364   {
365     0x02,
366     L"3D controller",
367     PCIBlankEntry
368   },
369   {
370     0x80,
371     L"Other display controller",
372     PCIBlankEntry
373   },
374   {
375     0x00,
376     NULL,
377     /* null string ends the list */PCIBlankEntry
378   }
379 };
380 
381 PCI_CLASS_ENTRY PCISubClass_04[] = {
382   {
383     0x00,
384     L"Video device",
385     PCIBlankEntry
386   },
387   {
388     0x01,
389     L"Audio device",
390     PCIBlankEntry
391   },
392   {
393     0x02,
394     L"Computer Telephony device",
395     PCIBlankEntry
396   },
397   {
398     0x03,
399     L"Mixed mode device",
400     PCIBlankEntry
401   },
402   {
403     0x80,
404     L"Other multimedia device",
405     PCIBlankEntry
406   },
407   {
408     0x00,
409     NULL,
410     /* null string ends the list */NULL
411   }
412 };
413 
414 PCI_CLASS_ENTRY PCISubClass_05[] = {
415   {
416     0x00,
417     L"RAM memory controller",
418     PCIBlankEntry
419   },
420   {
421     0x01,
422     L"Flash memory controller",
423     PCIBlankEntry
424   },
425   {
426     0x80,
427     L"Other memory controller",
428     PCIBlankEntry
429   },
430   {
431     0x00,
432     NULL,
433     /* null string ends the list */NULL
434   }
435 };
436 
437 PCI_CLASS_ENTRY PCISubClass_06[] = {
438   {
439     0x00,
440     L"Host/PCI bridge",
441     PCIBlankEntry
442   },
443   {
444     0x01,
445     L"PCI/ISA bridge",
446     PCIBlankEntry
447   },
448   {
449     0x02,
450     L"PCI/EISA bridge",
451     PCIBlankEntry
452   },
453   {
454     0x03,
455     L"PCI/Micro Channel bridge",
456     PCIBlankEntry
457   },
458   {
459     0x04,
460     L"PCI/PCI bridge",
461     PCIPIFClass_0604
462   },
463   {
464     0x05,
465     L"PCI/PCMCIA bridge",
466     PCIBlankEntry
467   },
468   {
469     0x06,
470     L"NuBus bridge",
471     PCIBlankEntry
472   },
473   {
474     0x07,
475     L"CardBus bridge",
476     PCIBlankEntry
477   },
478   {
479     0x08,
480     L"RACEway bridge",
481     PCIBlankEntry
482   },
483   {
484     0x09,
485     L"Semi-transparent PCI-to-PCI bridge",
486     PCIPIFClass_0609
487   },
488   {
489     0x0A,
490     L"InfiniBand-to-PCI host bridge",
491     PCIBlankEntry
492   },
493   {
494     0x0B,
495     L"Advanced Switching to PCI host bridge",
496     PCIPIFClass_060b
497   },
498   {
499     0x80,
500     L"Other bridge type",
501     PCIBlankEntry
502   },
503   {
504     0x00,
505     NULL,
506     /* null string ends the list */NULL
507   }
508 };
509 
510 PCI_CLASS_ENTRY PCISubClass_07[] = {
511   {
512     0x00,
513     L"Serial controller",
514     PCIPIFClass_0700
515   },
516   {
517     0x01,
518     L"Parallel port",
519     PCIPIFClass_0701
520   },
521   {
522     0x02,
523     L"Multiport serial controller",
524     PCIBlankEntry
525   },
526   {
527     0x03,
528     L"Modem",
529     PCIPIFClass_0703
530   },
531   {
532     0x04,
533     L"GPIB (IEEE 488.1/2) controller",
534     PCIBlankEntry
535   },
536   {
537     0x05,
538     L"Smart Card",
539     PCIBlankEntry
540   },
541   {
542     0x80,
543     L"Other communication device",
544     PCIBlankEntry
545   },
546   {
547     0x00,
548     NULL,
549     /* null string ends the list */NULL
550   }
551 };
552 
553 PCI_CLASS_ENTRY PCISubClass_08[] = {
554   {
555     0x00,
556     L"PIC",
557     PCIPIFClass_0800
558   },
559   {
560     0x01,
561     L"DMA controller",
562     PCIPIFClass_0801
563   },
564   {
565     0x02,
566     L"System timer",
567     PCIPIFClass_0802
568   },
569   {
570     0x03,
571     L"RTC controller",
572     PCIPIFClass_0803
573   },
574   {
575     0x04,
576     L"Generic PCI Hot-Plug controller",
577     PCIBlankEntry
578   },
579   {
580     0x05,
581     L"SD Host controller",
582     PCIBlankEntry
583   },
584   {
585     0x06,
586     L"IOMMU",
587     PCIBlankEntry
588   },
589   {
590     0x07,
591     L"Root Complex Event Collector",
592     PCIBlankEntry
593   },
594   {
595     0x80,
596     L"Other system peripheral",
597     PCIBlankEntry
598   },
599   {
600     0x00,
601     NULL,
602     /* null string ends the list */NULL
603   }
604 };
605 
606 PCI_CLASS_ENTRY PCISubClass_09[] = {
607   {
608     0x00,
609     L"Keyboard controller",
610     PCIBlankEntry
611   },
612   {
613     0x01,
614     L"Digitizer (pen)",
615     PCIBlankEntry
616   },
617   {
618     0x02,
619     L"Mouse controller",
620     PCIBlankEntry
621   },
622   {
623     0x03,
624     L"Scanner controller",
625     PCIBlankEntry
626   },
627   {
628     0x04,
629     L"Gameport controller",
630     PCIPIFClass_0904
631   },
632   {
633     0x80,
634     L"Other input controller",
635     PCIBlankEntry
636   },
637   {
638     0x00,
639     NULL,
640     /* null string ends the list */NULL
641   }
642 };
643 
644 PCI_CLASS_ENTRY PCISubClass_0a[] = {
645   {
646     0x00,
647     L"Generic docking station",
648     PCIBlankEntry
649   },
650   {
651     0x80,
652     L"Other type of docking station",
653     PCIBlankEntry
654   },
655   {
656     0x00,
657     NULL,
658     /* null string ends the list */NULL
659   }
660 };
661 
662 PCI_CLASS_ENTRY PCISubClass_0b[] = {
663   {
664     0x00,
665     L"386",
666     PCIBlankEntry
667   },
668   {
669     0x01,
670     L"486",
671     PCIBlankEntry
672   },
673   {
674     0x02,
675     L"Pentium",
676     PCIBlankEntry
677   },
678   {
679     0x10,
680     L"Alpha",
681     PCIBlankEntry
682   },
683   {
684     0x20,
685     L"PowerPC",
686     PCIBlankEntry
687   },
688   {
689     0x30,
690     L"MIPS",
691     PCIBlankEntry
692   },
693   {
694     0x40,
695     L"Co-processor",
696     PCIBlankEntry
697   },
698   {
699     0x80,
700     L"Other processor",
701     PCIBlankEntry
702   },
703   {
704     0x00,
705     NULL,
706     /* null string ends the list */NULL
707   }
708 };
709 
710 PCI_CLASS_ENTRY PCISubClass_0c[] = {
711   {
712     0x00,
713     L"IEEE 1394",
714     PCIPIFClass_0c00
715   },
716   {
717     0x01,
718     L"ACCESS.bus",
719     PCIBlankEntry
720   },
721   {
722     0x02,
723     L"SSA",
724     PCIBlankEntry
725   },
726   {
727     0x03,
728     L"USB",
729     PCIPIFClass_0c03
730   },
731   {
732     0x04,
733     L"Fibre Channel",
734     PCIBlankEntry
735   },
736   {
737     0x05,
738     L"System Management Bus",
739     PCIBlankEntry
740   },
741   {
742     0x06,
743     L"InfiniBand",
744     PCIBlankEntry
745   },
746   {
747     0x07,
748     L"IPMI",
749     PCIPIFClass_0c07
750   },
751   {
752     0x08,
753     L"SERCOS Interface Standard (IEC 61491)",
754     PCIBlankEntry
755   },
756   {
757     0x09,
758     L"CANbus",
759     PCIBlankEntry
760   },
761   {
762     0x80,
763     L"Other bus type",
764     PCIBlankEntry
765   },
766   {
767     0x00,
768     NULL,
769     /* null string ends the list */NULL
770   }
771 };
772 
773 PCI_CLASS_ENTRY PCISubClass_0d[] = {
774   {
775     0x00,
776     L"iRDA compatible controller",
777     PCIBlankEntry
778   },
779   {
780     0x01,
781     L"",
782     PCIPIFClass_0d01
783   },
784   {
785     0x10,
786     L"RF controller",
787     PCIBlankEntry
788   },
789   {
790     0x11,
791     L"Bluetooth",
792     PCIBlankEntry
793   },
794   {
795     0x12,
796     L"Broadband",
797     PCIBlankEntry
798   },
799   {
800     0x20,
801     L"Ethernet (802.11a - 5 GHz)",
802     PCIBlankEntry
803   },
804   {
805     0x21,
806     L"Ethernet (802.11b - 2.4 GHz)",
807     PCIBlankEntry
808   },
809   {
810     0x80,
811     L"Other type of wireless controller",
812     PCIBlankEntry
813   },
814   {
815     0x00,
816     NULL,
817     /* null string ends the list */NULL
818   }
819 };
820 
821 PCI_CLASS_ENTRY PCISubClass_0e[] = {
822   {
823     0x00,
824     L"I2O Architecture",
825     PCIPIFClass_0e00
826   },
827   {
828     0x00,
829     NULL,
830     /* null string ends the list */NULL
831   }
832 };
833 
834 PCI_CLASS_ENTRY PCISubClass_0f[] = {
835   {
836     0x01,
837     L"TV",
838     PCIBlankEntry
839   },
840   {
841     0x02,
842     L"Audio",
843     PCIBlankEntry
844   },
845   {
846     0x03,
847     L"Voice",
848     PCIBlankEntry
849   },
850   {
851     0x04,
852     L"Data",
853     PCIBlankEntry
854   },
855   {
856     0x80,
857     L"Other satellite communication controller",
858     PCIBlankEntry
859   },
860   {
861     0x00,
862     NULL,
863     /* null string ends the list */NULL
864   }
865 };
866 
867 PCI_CLASS_ENTRY PCISubClass_10[] = {
868   {
869     0x00,
870     L"Network & computing Encrypt/Decrypt",
871     PCIBlankEntry
872   },
873   {
874     0x01,
875     L"Entertainment Encrypt/Decrypt",
876     PCIBlankEntry
877   },
878   {
879     0x80,
880     L"Other Encrypt/Decrypt",
881     PCIBlankEntry
882   },
883   {
884     0x00,
885     NULL,
886     /* null string ends the list */NULL
887   }
888 };
889 
890 PCI_CLASS_ENTRY PCISubClass_11[] = {
891   {
892     0x00,
893     L"DPIO modules",
894     PCIBlankEntry
895   },
896   {
897     0x01,
898     L"Performance Counters",
899     PCIBlankEntry
900   },
901   {
902     0x10,
903     L"Communications synchronization plus time and frequency test/measurement ",
904     PCIBlankEntry
905   },
906   {
907     0x20,
908     L"Management card",
909     PCIBlankEntry
910   },
911   {
912     0x80,
913     L"Other DAQ & SP controllers",
914     PCIBlankEntry
915   },
916   {
917     0x00,
918     NULL,
919     /* null string ends the list */NULL
920   }
921 };
922 
923 PCI_CLASS_ENTRY PCISubClass_12[] = {
924   {
925     0x00,
926     L"Processing Accelerator",
927     PCIBlankEntry
928   },
929   {
930     0x00,
931     NULL,
932     /* null string ends the list */NULL
933   }
934 };
935 
936 PCI_CLASS_ENTRY PCISubClass_13[] = {
937   {
938     0x00,
939     L"Non-Essential Instrumentation Function",
940     PCIBlankEntry
941   },
942   {
943     0x00,
944     NULL,
945     /* null string ends the list */NULL
946   }
947 };
948 
949 //
950 // Programming Interface entries
951 //
952 PCI_CLASS_ENTRY PCIPIFClass_0100[] = {
953   {
954     0x00,
955     L"SCSI controller",
956     PCIBlankEntry
957   },
958   {
959     0x11,
960     L"SCSI storage device SOP using PQI",
961     PCIBlankEntry
962   },
963   {
964     0x12,
965     L"SCSI controller SOP using PQI",
966     PCIBlankEntry
967   },
968   {
969     0x13,
970     L"SCSI storage device and controller SOP using PQI",
971     PCIBlankEntry
972   },
973   {
974     0x21,
975     L"SCSI storage device SOP using NVMe",
976     PCIBlankEntry
977   },
978   {
979     0x00,
980     NULL,
981     /* null string ends the list */NULL
982   }
983 };
984 
985 PCI_CLASS_ENTRY PCIPIFClass_0101[] = {
986   {
987     0x00,
988     L"",
989     PCIBlankEntry
990   },
991   {
992     0x01,
993     L"OM-primary",
994     PCIBlankEntry
995   },
996   {
997     0x02,
998     L"PI-primary",
999     PCIBlankEntry
1000   },
1001   {
1002     0x03,
1003     L"OM/PI-primary",
1004     PCIBlankEntry
1005   },
1006   {
1007     0x04,
1008     L"OM-secondary",
1009     PCIBlankEntry
1010   },
1011   {
1012     0x05,
1013     L"OM-primary, OM-secondary",
1014     PCIBlankEntry
1015   },
1016   {
1017     0x06,
1018     L"PI-primary, OM-secondary",
1019     PCIBlankEntry
1020   },
1021   {
1022     0x07,
1023     L"OM/PI-primary, OM-secondary",
1024     PCIBlankEntry
1025   },
1026   {
1027     0x08,
1028     L"OM-secondary",
1029     PCIBlankEntry
1030   },
1031   {
1032     0x09,
1033     L"OM-primary, PI-secondary",
1034     PCIBlankEntry
1035   },
1036   {
1037     0x0a,
1038     L"PI-primary, PI-secondary",
1039     PCIBlankEntry
1040   },
1041   {
1042     0x0b,
1043     L"OM/PI-primary, PI-secondary",
1044     PCIBlankEntry
1045   },
1046   {
1047     0x0c,
1048     L"OM-secondary",
1049     PCIBlankEntry
1050   },
1051   {
1052     0x0d,
1053     L"OM-primary, OM/PI-secondary",
1054     PCIBlankEntry
1055   },
1056   {
1057     0x0e,
1058     L"PI-primary, OM/PI-secondary",
1059     PCIBlankEntry
1060   },
1061   {
1062     0x0f,
1063     L"OM/PI-primary, OM/PI-secondary",
1064     PCIBlankEntry
1065   },
1066   {
1067     0x80,
1068     L"Master",
1069     PCIBlankEntry
1070   },
1071   {
1072     0x81,
1073     L"Master, OM-primary",
1074     PCIBlankEntry
1075   },
1076   {
1077     0x82,
1078     L"Master, PI-primary",
1079     PCIBlankEntry
1080   },
1081   {
1082     0x83,
1083     L"Master, OM/PI-primary",
1084     PCIBlankEntry
1085   },
1086   {
1087     0x84,
1088     L"Master, OM-secondary",
1089     PCIBlankEntry
1090   },
1091   {
1092     0x85,
1093     L"Master, OM-primary, OM-secondary",
1094     PCIBlankEntry
1095   },
1096   {
1097     0x86,
1098     L"Master, PI-primary, OM-secondary",
1099     PCIBlankEntry
1100   },
1101   {
1102     0x87,
1103     L"Master, OM/PI-primary, OM-secondary",
1104     PCIBlankEntry
1105   },
1106   {
1107     0x88,
1108     L"Master, OM-secondary",
1109     PCIBlankEntry
1110   },
1111   {
1112     0x89,
1113     L"Master, OM-primary, PI-secondary",
1114     PCIBlankEntry
1115   },
1116   {
1117     0x8a,
1118     L"Master, PI-primary, PI-secondary",
1119     PCIBlankEntry
1120   },
1121   {
1122     0x8b,
1123     L"Master, OM/PI-primary, PI-secondary",
1124     PCIBlankEntry
1125   },
1126   {
1127     0x8c,
1128     L"Master, OM-secondary",
1129     PCIBlankEntry
1130   },
1131   {
1132     0x8d,
1133     L"Master, OM-primary, OM/PI-secondary",
1134     PCIBlankEntry
1135   },
1136   {
1137     0x8e,
1138     L"Master, PI-primary, OM/PI-secondary",
1139     PCIBlankEntry
1140   },
1141   {
1142     0x8f,
1143     L"Master, OM/PI-primary, OM/PI-secondary",
1144     PCIBlankEntry
1145   },
1146   {
1147     0x00,
1148     NULL,
1149     /* null string ends the list */NULL
1150   }
1151 };
1152 
1153 PCI_CLASS_ENTRY PCIPIFClass_0105[] = {
1154   {
1155     0x20,
1156     L"Single stepping",
1157     PCIBlankEntry
1158   },
1159   {
1160     0x30,
1161     L"Continuous operation",
1162     PCIBlankEntry
1163   },
1164   {
1165     0x00,
1166     NULL,
1167     /* null string ends the list */NULL
1168   }
1169 };
1170 
1171 PCI_CLASS_ENTRY PCIPIFClass_0106[] = {
1172   {
1173     0x00,
1174     L"",
1175     PCIBlankEntry
1176   },
1177   {
1178     0x01,
1179     L"AHCI",
1180     PCIBlankEntry
1181   },
1182   {
1183     0x02,
1184     L"Serial Storage Bus",
1185     PCIBlankEntry
1186   },
1187   {
1188     0x00,
1189     NULL,
1190     /* null string ends the list */NULL
1191   }
1192 };
1193 
1194 PCI_CLASS_ENTRY PCIPIFClass_0107[] = {
1195   {
1196     0x00,
1197     L"",
1198     PCIBlankEntry
1199   },
1200   {
1201     0x01,
1202     L"Obsolete",
1203     PCIBlankEntry
1204   },
1205   {
1206     0x00,
1207     NULL,
1208     /* null string ends the list */NULL
1209   }
1210 };
1211 
1212 PCI_CLASS_ENTRY PCIPIFClass_0108[] = {
1213   {
1214     0x00,
1215     L"",
1216     PCIBlankEntry
1217   },
1218   {
1219     0x01,
1220     L"NVMHCI",
1221     PCIBlankEntry
1222   },
1223   {
1224     0x02,
1225     L"NVM Express",
1226     PCIBlankEntry
1227   },
1228   {
1229     0x00,
1230     NULL,
1231     /* null string ends the list */NULL
1232   }
1233 };
1234 
1235 PCI_CLASS_ENTRY PCIPIFClass_0109[] = {
1236   {
1237     0x00,
1238     L"",
1239     PCIBlankEntry
1240   },
1241   {
1242     0x01,
1243     L"UFSHCI",
1244     PCIBlankEntry
1245   },
1246   {
1247     0x00,
1248     NULL,
1249     /* null string ends the list */NULL
1250   }
1251 };
1252 
1253 PCI_CLASS_ENTRY PCIPIFClass_0300[] = {
1254   {
1255     0x00,
1256     L"VGA compatible",
1257     PCIBlankEntry
1258   },
1259   {
1260     0x01,
1261     L"8514 compatible",
1262     PCIBlankEntry
1263   },
1264   {
1265     0x00,
1266     NULL,
1267     /* null string ends the list */NULL
1268   }
1269 };
1270 
1271 PCI_CLASS_ENTRY PCIPIFClass_0604[] = {
1272   {
1273     0x00,
1274     L"",
1275     PCIBlankEntry
1276   },
1277   {
1278     0x01,
1279     L"Subtractive decode",
1280     PCIBlankEntry
1281   },
1282   {
1283     0x00,
1284     NULL,
1285     /* null string ends the list */NULL
1286   }
1287 };
1288 
1289 PCI_CLASS_ENTRY PCIPIFClass_0609[] = {
1290   {
1291     0x40,
1292     L"Primary PCI bus side facing the system host processor",
1293     PCIBlankEntry
1294   },
1295   {
1296     0x80,
1297     L"Secondary PCI bus side facing the system host processor",
1298     PCIBlankEntry
1299   },
1300   {
1301     0x00,
1302     NULL,
1303     /* null string ends the list */NULL
1304   }
1305 };
1306 
1307 PCI_CLASS_ENTRY PCIPIFClass_060b[] = {
1308   {
1309     0x00,
1310     L"Custom",
1311     PCIBlankEntry
1312   },
1313   {
1314     0x01,
1315     L"ASI-SIG Defined Portal",
1316     PCIBlankEntry
1317   },
1318   {
1319     0x00,
1320     NULL,
1321     /* null string ends the list */NULL
1322   }
1323 };
1324 
1325 PCI_CLASS_ENTRY PCIPIFClass_0700[] = {
1326   {
1327     0x00,
1328     L"Generic XT-compatible",
1329     PCIBlankEntry
1330   },
1331   {
1332     0x01,
1333     L"16450-compatible",
1334     PCIBlankEntry
1335   },
1336   {
1337     0x02,
1338     L"16550-compatible",
1339     PCIBlankEntry
1340   },
1341   {
1342     0x03,
1343     L"16650-compatible",
1344     PCIBlankEntry
1345   },
1346   {
1347     0x04,
1348     L"16750-compatible",
1349     PCIBlankEntry
1350   },
1351   {
1352     0x05,
1353     L"16850-compatible",
1354     PCIBlankEntry
1355   },
1356   {
1357     0x06,
1358     L"16950-compatible",
1359     PCIBlankEntry
1360   },
1361   {
1362     0x00,
1363     NULL,
1364     /* null string ends the list */NULL
1365   }
1366 };
1367 
1368 PCI_CLASS_ENTRY PCIPIFClass_0701[] = {
1369   {
1370     0x00,
1371     L"",
1372     PCIBlankEntry
1373   },
1374   {
1375     0x01,
1376     L"Bi-directional",
1377     PCIBlankEntry
1378   },
1379   {
1380     0x02,
1381     L"ECP 1.X-compliant",
1382     PCIBlankEntry
1383   },
1384   {
1385     0x03,
1386     L"IEEE 1284",
1387     PCIBlankEntry
1388   },
1389   {
1390     0xfe,
1391     L"IEEE 1284 target (not a controller)",
1392     PCIBlankEntry
1393   },
1394   {
1395     0x00,
1396     NULL,
1397     /* null string ends the list */NULL
1398   }
1399 };
1400 
1401 PCI_CLASS_ENTRY PCIPIFClass_0703[] = {
1402   {
1403     0x00,
1404     L"Generic",
1405     PCIBlankEntry
1406   },
1407   {
1408     0x01,
1409     L"Hayes-compatible 16450",
1410     PCIBlankEntry
1411   },
1412   {
1413     0x02,
1414     L"Hayes-compatible 16550",
1415     PCIBlankEntry
1416   },
1417   {
1418     0x03,
1419     L"Hayes-compatible 16650",
1420     PCIBlankEntry
1421   },
1422   {
1423     0x04,
1424     L"Hayes-compatible 16750",
1425     PCIBlankEntry
1426   },
1427   {
1428     0x00,
1429     NULL,
1430     /* null string ends the list */NULL
1431   }
1432 };
1433 
1434 PCI_CLASS_ENTRY PCIPIFClass_0800[] = {
1435   {
1436     0x00,
1437     L"Generic 8259",
1438     PCIBlankEntry
1439   },
1440   {
1441     0x01,
1442     L"ISA",
1443     PCIBlankEntry
1444   },
1445   {
1446     0x02,
1447     L"EISA",
1448     PCIBlankEntry
1449   },
1450   {
1451     0x10,
1452     L"IO APIC",
1453     PCIBlankEntry
1454   },
1455   {
1456     0x20,
1457     L"IO(x) APIC interrupt controller",
1458     PCIBlankEntry
1459   },
1460   {
1461     0x00,
1462     NULL,
1463     /* null string ends the list */NULL
1464   }
1465 };
1466 
1467 PCI_CLASS_ENTRY PCIPIFClass_0801[] = {
1468   {
1469     0x00,
1470     L"Generic 8237",
1471     PCIBlankEntry
1472   },
1473   {
1474     0x01,
1475     L"ISA",
1476     PCIBlankEntry
1477   },
1478   {
1479     0x02,
1480     L"EISA",
1481     PCIBlankEntry
1482   },
1483   {
1484     0x00,
1485     NULL,
1486     /* null string ends the list */NULL
1487   }
1488 };
1489 
1490 PCI_CLASS_ENTRY PCIPIFClass_0802[] = {
1491   {
1492     0x00,
1493     L"Generic 8254",
1494     PCIBlankEntry
1495   },
1496   {
1497     0x01,
1498     L"ISA",
1499     PCIBlankEntry
1500   },
1501   {
1502     0x02,
1503     L"EISA",
1504     PCIBlankEntry
1505   },
1506   {
1507     0x00,
1508     NULL,
1509     /* null string ends the list */NULL
1510   }
1511 };
1512 
1513 PCI_CLASS_ENTRY PCIPIFClass_0803[] = {
1514   {
1515     0x00,
1516     L"Generic",
1517     PCIBlankEntry
1518   },
1519   {
1520     0x01,
1521     L"ISA",
1522     PCIBlankEntry
1523   },
1524   {
1525     0x02,
1526     L"EISA",
1527     PCIBlankEntry
1528   },
1529   {
1530     0x00,
1531     NULL,
1532     /* null string ends the list */NULL
1533   }
1534 };
1535 
1536 PCI_CLASS_ENTRY PCIPIFClass_0904[] = {
1537   {
1538     0x00,
1539     L"Generic",
1540     PCIBlankEntry
1541   },
1542   {
1543     0x10,
1544     L"",
1545     PCIBlankEntry
1546   },
1547   {
1548     0x00,
1549     NULL,
1550     /* null string ends the list */NULL
1551   }
1552 };
1553 
1554 PCI_CLASS_ENTRY PCIPIFClass_0c00[] = {
1555   {
1556     0x00,
1557     L"",
1558     PCIBlankEntry
1559   },
1560   {
1561     0x10,
1562     L"Using 1394 OpenHCI spec",
1563     PCIBlankEntry
1564   },
1565   {
1566     0x00,
1567     NULL,
1568     /* null string ends the list */NULL
1569   }
1570 };
1571 
1572 PCI_CLASS_ENTRY PCIPIFClass_0c03[] = {
1573   {
1574     0x00,
1575     L"UHCI",
1576     PCIBlankEntry
1577   },
1578   {
1579     0x10,
1580     L"OHCI",
1581     PCIBlankEntry
1582   },
1583   {
1584     0x20,
1585     L"EHCI",
1586     PCIBlankEntry
1587   },
1588   {
1589     0x30,
1590     L"xHCI",
1591     PCIBlankEntry
1592   },
1593   {
1594     0x80,
1595     L"No specific programming interface",
1596     PCIBlankEntry
1597   },
1598   {
1599     0xfe,
1600     L"(Not Host Controller)",
1601     PCIBlankEntry
1602   },
1603   {
1604     0x00,
1605     NULL,
1606     /* null string ends the list */NULL
1607   }
1608 };
1609 
1610 PCI_CLASS_ENTRY PCIPIFClass_0c07[] = {
1611   {
1612     0x00,
1613     L"SMIC",
1614     PCIBlankEntry
1615   },
1616   {
1617     0x01,
1618     L"Keyboard Controller Style",
1619     PCIBlankEntry
1620   },
1621   {
1622     0x02,
1623     L"Block Transfer",
1624     PCIBlankEntry
1625   },
1626   {
1627     0x00,
1628     NULL,
1629     /* null string ends the list */NULL
1630   }
1631 };
1632 
1633 PCI_CLASS_ENTRY PCIPIFClass_0d01[] = {
1634   {
1635     0x00,
1636     L"Consumer IR controller",
1637     PCIBlankEntry
1638   },
1639   {
1640     0x10,
1641     L"UWB Radio controller",
1642     PCIBlankEntry
1643   },
1644   {
1645     0x00,
1646     NULL,
1647     /* null string ends the list */NULL
1648   }
1649 };
1650 
1651 PCI_CLASS_ENTRY PCIPIFClass_0e00[] = {
1652   {
1653     0x00,
1654     L"Message FIFO at offset 40h",
1655     PCIBlankEntry
1656   },
1657   {
1658     0x01,
1659     L"",
1660     PCIBlankEntry
1661   },
1662   {
1663     0x00,
1664     NULL,
1665     /* null string ends the list */NULL
1666   }
1667 };
1668 
1669 
1670 /**
1671   Generates printable Unicode strings that represent PCI device class,
1672   subclass and programmed I/F based on a value passed to the function.
1673 
1674   @param[in] ClassCode      Value representing the PCI "Class Code" register read from a
1675                  PCI device. The encodings are:
1676                      bits 23:16 - Base Class Code
1677                      bits 15:8  - Sub-Class Code
1678                      bits  7:0  - Programming Interface
1679   @param[in, out] ClassStrings   Pointer of PCI_CLASS_STRINGS structure, which contains
1680                  printable class strings corresponding to ClassCode. The
1681                  caller must not modify the strings that are pointed by
1682                  the fields in ClassStrings.
1683 **/
1684 VOID
PciGetClassStrings(IN UINT32 ClassCode,IN OUT PCI_CLASS_STRINGS * ClassStrings)1685 PciGetClassStrings (
1686   IN      UINT32               ClassCode,
1687   IN OUT  PCI_CLASS_STRINGS    *ClassStrings
1688   )
1689 {
1690   INTN            Index;
1691   UINT8           Code;
1692   PCI_CLASS_ENTRY *CurrentClass;
1693 
1694   //
1695   // Assume no strings found
1696   //
1697   ClassStrings->BaseClass = L"UNDEFINED";
1698   ClassStrings->SubClass  = L"UNDEFINED";
1699   ClassStrings->PIFClass  = L"UNDEFINED";
1700 
1701   CurrentClass = gClassStringList;
1702   Code = (UINT8) (ClassCode >> 16);
1703   Index = 0;
1704 
1705   //
1706   // Go through all entries of the base class, until the entry with a matching
1707   // base class code is found. If reaches an entry with a null description
1708   // text, the last entry is met, which means no text for the base class was
1709   // found, so no more action is needed.
1710   //
1711   while (Code != CurrentClass[Index].Code) {
1712     if (NULL == CurrentClass[Index].DescText) {
1713       return ;
1714     }
1715 
1716     Index++;
1717   }
1718   //
1719   // A base class was found. Assign description, and check if this class has
1720   // sub-class defined. If sub-class defined, no more action is needed,
1721   // otherwise, continue to find description for the sub-class code.
1722   //
1723   ClassStrings->BaseClass = CurrentClass[Index].DescText;
1724   if (NULL == CurrentClass[Index].LowerLevelClass) {
1725     return ;
1726   }
1727   //
1728   // find Subclass entry
1729   //
1730   CurrentClass  = CurrentClass[Index].LowerLevelClass;
1731   Code          = (UINT8) (ClassCode >> 8);
1732   Index         = 0;
1733 
1734   //
1735   // Go through all entries of the sub-class, until the entry with a matching
1736   // sub-class code is found. If reaches an entry with a null description
1737   // text, the last entry is met, which means no text for the sub-class was
1738   // found, so no more action is needed.
1739   //
1740   while (Code != CurrentClass[Index].Code) {
1741     if (NULL == CurrentClass[Index].DescText) {
1742       return ;
1743     }
1744 
1745     Index++;
1746   }
1747   //
1748   // A class was found for the sub-class code. Assign description, and check if
1749   // this sub-class has programming interface defined. If no, no more action is
1750   // needed, otherwise, continue to find description for the programming
1751   // interface.
1752   //
1753   ClassStrings->SubClass = CurrentClass[Index].DescText;
1754   if (NULL == CurrentClass[Index].LowerLevelClass) {
1755     return ;
1756   }
1757   //
1758   // Find programming interface entry
1759   //
1760   CurrentClass  = CurrentClass[Index].LowerLevelClass;
1761   Code          = (UINT8) ClassCode;
1762   Index         = 0;
1763 
1764   //
1765   // Go through all entries of the I/F entries, until the entry with a
1766   // matching I/F code is found. If reaches an entry with a null description
1767   // text, the last entry is met, which means no text was found, so no more
1768   // action is needed.
1769   //
1770   while (Code != CurrentClass[Index].Code) {
1771     if (NULL == CurrentClass[Index].DescText) {
1772       return ;
1773     }
1774 
1775     Index++;
1776   }
1777   //
1778   // A class was found for the I/F code. Assign description, done!
1779   //
1780   ClassStrings->PIFClass = CurrentClass[Index].DescText;
1781   return ;
1782 }
1783 
1784 /**
1785   Print strings that represent PCI device class, subclass and programmed I/F.
1786 
1787   @param[in] ClassCodePtr   Points to the memory which stores register Class Code in PCI
1788                             configuration space.
1789   @param[in] IncludePIF     If the printed string should include the programming I/F part
1790 **/
1791 VOID
PciPrintClassCode(IN UINT8 * ClassCodePtr,IN BOOLEAN IncludePIF)1792 PciPrintClassCode (
1793   IN      UINT8               *ClassCodePtr,
1794   IN      BOOLEAN             IncludePIF
1795   )
1796 {
1797   UINT32            ClassCode;
1798   PCI_CLASS_STRINGS ClassStrings;
1799 
1800   ClassCode = 0;
1801   ClassCode |= (UINT32)ClassCodePtr[0];
1802   ClassCode |= (UINT32)(ClassCodePtr[1] << 8);
1803   ClassCode |= (UINT32)(ClassCodePtr[2] << 16);
1804 
1805   //
1806   // Get name from class code
1807   //
1808   PciGetClassStrings (ClassCode, &ClassStrings);
1809 
1810   if (IncludePIF) {
1811     //
1812     // Print base class, sub class, and programming inferface name
1813     //
1814     ShellPrintEx (-1, -1, L"%s - %s - %s",
1815       ClassStrings.BaseClass,
1816       ClassStrings.SubClass,
1817       ClassStrings.PIFClass
1818      );
1819 
1820   } else {
1821     //
1822     // Only print base class and sub class name
1823     //
1824     ShellPrintEx (-1, -1, L"%s - %s",
1825       ClassStrings.BaseClass,
1826       ClassStrings.SubClass
1827     );
1828   }
1829 }
1830 
1831 /**
1832   This function finds out the protocol which is in charge of the given
1833   segment, and its bus range covers the current bus number. It lookes
1834   each instances of RootBridgeIoProtocol handle, until the one meets the
1835   criteria is found.
1836 
1837   @param[in] HandleBuf       Buffer which holds all PCI_ROOT_BRIDIGE_IO_PROTOCOL handles.
1838   @param[in] HandleCount     Count of all PCI_ROOT_BRIDIGE_IO_PROTOCOL handles.
1839   @param[in] Segment         Segment number of device we are dealing with.
1840   @param[in] Bus             Bus number of device we are dealing with.
1841   @param[out] IoDev          Handle used to access configuration space of PCI device.
1842 
1843   @retval EFI_SUCCESS             The command completed successfully.
1844   @retval EFI_INVALID_PARAMETER   Invalid parameter.
1845 
1846 **/
1847 EFI_STATUS
1848 PciFindProtocolInterface (
1849   IN  EFI_HANDLE                            *HandleBuf,
1850   IN  UINTN                                 HandleCount,
1851   IN  UINT16                                Segment,
1852   IN  UINT16                                Bus,
1853   OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL       **IoDev
1854   );
1855 
1856 /**
1857   This function gets the protocol interface from the given handle, and
1858   obtains its address space descriptors.
1859 
1860   @param[in] Handle          The PCI_ROOT_BRIDIGE_IO_PROTOCOL handle.
1861   @param[out] IoDev          Handle used to access configuration space of PCI device.
1862   @param[out] Descriptors    Points to the address space descriptors.
1863 
1864   @retval EFI_SUCCESS     The command completed successfully
1865 **/
1866 EFI_STATUS
1867 PciGetProtocolAndResource (
1868   IN  EFI_HANDLE                            Handle,
1869   OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL       **IoDev,
1870   OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR     **Descriptors
1871   );
1872 
1873 /**
1874   This function get the next bus range of given address space descriptors.
1875   It also moves the pointer backward a node, to get prepared to be called
1876   again.
1877 
1878   @param[in, out] Descriptors Points to current position of a serial of address space
1879                               descriptors.
1880   @param[out] MinBus          The lower range of bus number.
1881   @param[out] MaxBus          The upper range of bus number.
1882   @param[out] IsEnd           Meet end of the serial of descriptors.
1883 
1884   @retval EFI_SUCCESS     The command completed successfully.
1885 **/
1886 EFI_STATUS
1887 PciGetNextBusRange (
1888   IN OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  **Descriptors,
1889   OUT    UINT16                             *MinBus,
1890   OUT    UINT16                             *MaxBus,
1891   OUT    BOOLEAN                            *IsEnd
1892   );
1893 
1894 /**
1895   Explain the data in PCI configuration space. The part which is common for
1896   PCI device and bridge is interpreted in this function. It calls other
1897   functions to interpret data unique for device or bridge.
1898 
1899   @param[in] ConfigSpace     Data in PCI configuration space.
1900   @param[in] Address         Address used to access configuration space of this PCI device.
1901   @param[in] IoDev           Handle used to access configuration space of PCI device.
1902 **/
1903 VOID
1904 PciExplainPci (
1905   IN PCI_CONFIG_SPACE                       *ConfigSpace,
1906   IN UINT64                                 Address,
1907   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *IoDev
1908   );
1909 
1910 /**
1911   Explain the device specific part of data in PCI configuration space.
1912 
1913   @param[in] Device          Data in PCI configuration space.
1914   @param[in] Address         Address used to access configuration space of this PCI device.
1915   @param[in] IoDev           Handle used to access configuration space of PCI device.
1916 
1917   @retval EFI_SUCCESS     The command completed successfully.
1918 **/
1919 EFI_STATUS
1920 PciExplainDeviceData (
1921   IN PCI_DEVICE_HEADER_TYPE_REGION          *Device,
1922   IN UINT64                                 Address,
1923   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *IoDev
1924   );
1925 
1926 /**
1927   Explain the bridge specific part of data in PCI configuration space.
1928 
1929   @param[in] Bridge          Bridge specific data region in PCI configuration space.
1930   @param[in] Address         Address used to access configuration space of this PCI device.
1931   @param[in] IoDev           Handle used to access configuration space of PCI device.
1932 
1933   @retval EFI_SUCCESS     The command completed successfully.
1934 **/
1935 EFI_STATUS
1936 PciExplainBridgeData (
1937   IN  PCI_BRIDGE_CONTROL_REGISTER           *Bridge,
1938   IN  UINT64                                Address,
1939   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL       *IoDev
1940   );
1941 
1942 /**
1943   Explain the Base Address Register(Bar) in PCI configuration space.
1944 
1945   @param[in] Bar              Points to the Base Address Register intended to interpret.
1946   @param[in] Command          Points to the register Command.
1947   @param[in] Address          Address used to access configuration space of this PCI device.
1948   @param[in] IoDev            Handle used to access configuration space of PCI device.
1949   @param[in, out] Index       The Index.
1950 
1951   @retval EFI_SUCCESS     The command completed successfully.
1952 **/
1953 EFI_STATUS
1954 PciExplainBar (
1955   IN UINT32                                 *Bar,
1956   IN UINT16                                 *Command,
1957   IN UINT64                                 Address,
1958   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *IoDev,
1959   IN OUT UINTN                              *Index
1960   );
1961 
1962 /**
1963   Explain the cardbus specific part of data in PCI configuration space.
1964 
1965   @param[in] CardBus         CardBus specific region of PCI configuration space.
1966   @param[in] Address         Address used to access configuration space of this PCI device.
1967   @param[in] IoDev           Handle used to access configuration space of PCI device.
1968 
1969   @retval EFI_SUCCESS     The command completed successfully.
1970 **/
1971 EFI_STATUS
1972 PciExplainCardBusData (
1973   IN PCI_CARDBUS_CONTROL_REGISTER           *CardBus,
1974   IN UINT64                                 Address,
1975   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *IoDev
1976   );
1977 
1978 /**
1979   Explain each meaningful bit of register Status. The definition of Status is
1980   slightly different depending on the PCI header type.
1981 
1982   @param[in] Status          Points to the content of register Status.
1983   @param[in] MainStatus      Indicates if this register is main status(not secondary
1984                              status).
1985   @param[in] HeaderType      Header type of this PCI device.
1986 
1987   @retval EFI_SUCCESS     The command completed successfully.
1988 **/
1989 EFI_STATUS
1990 PciExplainStatus (
1991   IN UINT16                                 *Status,
1992   IN BOOLEAN                                MainStatus,
1993   IN PCI_HEADER_TYPE                        HeaderType
1994   );
1995 
1996 /**
1997   Explain each meaningful bit of register Command.
1998 
1999   @param[in] Command         Points to the content of register Command.
2000 
2001   @retval EFI_SUCCESS     The command completed successfully.
2002 **/
2003 EFI_STATUS
2004 PciExplainCommand (
2005   IN UINT16                                 *Command
2006   );
2007 
2008 /**
2009   Explain each meaningful bit of register Bridge Control.
2010 
2011   @param[in] BridgeControl   Points to the content of register Bridge Control.
2012   @param[in] HeaderType      The headertype.
2013 
2014   @retval EFI_SUCCESS     The command completed successfully.
2015 **/
2016 EFI_STATUS
2017 PciExplainBridgeControl (
2018   IN UINT16                                 *BridgeControl,
2019   IN PCI_HEADER_TYPE                        HeaderType
2020   );
2021 
2022 /**
2023   Locate capability register block per capability ID.
2024 
2025   @param[in] ConfigSpace       Data in PCI configuration space.
2026   @param[in] CapabilityId      The capability ID.
2027 
2028   @return   The offset of the register block per capability ID.
2029 **/
2030 UINT8
2031 LocatePciCapability (
2032   IN PCI_CONFIG_SPACE   *ConfigSpace,
2033   IN UINT8              CapabilityId
2034   );
2035 
2036 /**
2037   Display Pcie device structure.
2038 
2039   @param[in] PciExpressCap       PCI Express capability buffer.
2040   @param[in] ExtendedConfigSpace PCI Express extended configuration space.
2041   @param[in] ExtendedCapability  PCI Express extended capability ID to explain.
2042 **/
2043 VOID
2044 PciExplainPciExpress (
2045   IN  PCI_CAPABILITY_PCIEXP                  *PciExpressCap,
2046   IN  UINT8                                  *ExtendedConfigSpace,
2047   IN CONST UINT16                            ExtendedCapability
2048   );
2049 
2050 /**
2051   Print out information of the capability information.
2052 
2053   @param[in] PciExpressCap  The pointer to the structure about the device.
2054 
2055   @retval EFI_SUCCESS   The operation was successful.
2056 **/
2057 EFI_STATUS
2058 ExplainPcieCapReg (
2059   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
2060   );
2061 
2062 /**
2063   Print out information of the device capability information.
2064 
2065   @param[in] PciExpressCap  The pointer to the structure about the device.
2066 
2067   @retval EFI_SUCCESS   The operation was successful.
2068 **/
2069 EFI_STATUS
2070 ExplainPcieDeviceCap (
2071   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
2072   );
2073 
2074 /**
2075   Print out information of the device control information.
2076 
2077   @param[in] PciExpressCap  The pointer to the structure about the device.
2078 
2079   @retval EFI_SUCCESS   The operation was successful.
2080 **/
2081 EFI_STATUS
2082 ExplainPcieDeviceControl (
2083   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
2084   );
2085 
2086 /**
2087   Print out information of the device status information.
2088 
2089   @param[in] PciExpressCap  The pointer to the structure about the device.
2090 
2091   @retval EFI_SUCCESS   The operation was successful.
2092 **/
2093 EFI_STATUS
2094 ExplainPcieDeviceStatus (
2095   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
2096   );
2097 
2098 /**
2099   Print out information of the device link information.
2100 
2101   @param[in] PciExpressCap  The pointer to the structure about the device.
2102 
2103   @retval EFI_SUCCESS   The operation was successful.
2104 **/
2105 EFI_STATUS
2106 ExplainPcieLinkCap (
2107   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
2108   );
2109 
2110 /**
2111   Print out information of the device link control information.
2112 
2113   @param[in] PciExpressCap  The pointer to the structure about the device.
2114 
2115   @retval EFI_SUCCESS   The operation was successful.
2116 **/
2117 EFI_STATUS
2118 ExplainPcieLinkControl (
2119   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
2120   );
2121 
2122 /**
2123   Print out information of the device link status information.
2124 
2125   @param[in] PciExpressCap  The pointer to the structure about the device.
2126 
2127   @retval EFI_SUCCESS   The operation was successful.
2128 **/
2129 EFI_STATUS
2130 ExplainPcieLinkStatus (
2131   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
2132   );
2133 
2134 /**
2135   Print out information of the device slot information.
2136 
2137   @param[in] PciExpressCap  The pointer to the structure about the device.
2138 
2139   @retval EFI_SUCCESS   The operation was successful.
2140 **/
2141 EFI_STATUS
2142 ExplainPcieSlotCap (
2143   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
2144   );
2145 
2146 /**
2147   Print out information of the device slot control information.
2148 
2149   @param[in] PciExpressCap  The pointer to the structure about the device.
2150 
2151   @retval EFI_SUCCESS   The operation was successful.
2152 **/
2153 EFI_STATUS
2154 ExplainPcieSlotControl (
2155   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
2156   );
2157 
2158 /**
2159   Print out information of the device slot status information.
2160 
2161   @param[in] PciExpressCap  The pointer to the structure about the device.
2162 
2163   @retval EFI_SUCCESS   The operation was successful.
2164 **/
2165 EFI_STATUS
2166 ExplainPcieSlotStatus (
2167   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
2168   );
2169 
2170 /**
2171   Print out information of the device root information.
2172 
2173   @param[in] PciExpressCap  The pointer to the structure about the device.
2174 
2175   @retval EFI_SUCCESS   The operation was successful.
2176 **/
2177 EFI_STATUS
2178 ExplainPcieRootControl (
2179   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
2180   );
2181 
2182 /**
2183   Print out information of the device root capability information.
2184 
2185   @param[in] PciExpressCap  The pointer to the structure about the device.
2186 
2187   @retval EFI_SUCCESS   The operation was successful.
2188 **/
2189 EFI_STATUS
2190 ExplainPcieRootCap (
2191   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
2192   );
2193 
2194 /**
2195   Print out information of the device root status information.
2196 
2197   @param[in] PciExpressCap  The pointer to the structure about the device.
2198 
2199   @retval EFI_SUCCESS   The operation was successful.
2200 **/
2201 EFI_STATUS
2202 ExplainPcieRootStatus (
2203   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
2204   );
2205 
2206 typedef EFI_STATUS (*PCIE_EXPLAIN_FUNCTION) (IN PCI_CAPABILITY_PCIEXP *PciExpressCap);
2207 
2208 typedef enum {
2209   FieldWidthUINT8,
2210   FieldWidthUINT16,
2211   FieldWidthUINT32
2212 } PCIE_CAPREG_FIELD_WIDTH;
2213 
2214 typedef enum {
2215   PcieExplainTypeCommon,
2216   PcieExplainTypeDevice,
2217   PcieExplainTypeLink,
2218   PcieExplainTypeSlot,
2219   PcieExplainTypeRoot,
2220   PcieExplainTypeMax
2221 } PCIE_EXPLAIN_TYPE;
2222 
2223 typedef struct
2224 {
2225   UINT16                  Token;
2226   UINTN                   Offset;
2227   PCIE_CAPREG_FIELD_WIDTH Width;
2228   PCIE_EXPLAIN_FUNCTION   Func;
2229   PCIE_EXPLAIN_TYPE       Type;
2230 } PCIE_EXPLAIN_STRUCT;
2231 
2232 PCIE_EXPLAIN_STRUCT PcieExplainList[] = {
2233   {
2234     STRING_TOKEN (STR_PCIEX_CAPABILITY_CAPID),
2235     0x00,
2236     FieldWidthUINT8,
2237     NULL,
2238     PcieExplainTypeCommon
2239   },
2240   {
2241     STRING_TOKEN (STR_PCIEX_NEXTCAP_PTR),
2242     0x01,
2243     FieldWidthUINT8,
2244     NULL,
2245     PcieExplainTypeCommon
2246   },
2247   {
2248     STRING_TOKEN (STR_PCIEX_CAP_REGISTER),
2249     0x02,
2250     FieldWidthUINT16,
2251     ExplainPcieCapReg,
2252     PcieExplainTypeCommon
2253   },
2254   {
2255     STRING_TOKEN (STR_PCIEX_DEVICE_CAP),
2256     0x04,
2257     FieldWidthUINT32,
2258     ExplainPcieDeviceCap,
2259     PcieExplainTypeDevice
2260   },
2261   {
2262     STRING_TOKEN (STR_PCIEX_DEVICE_CONTROL),
2263     0x08,
2264     FieldWidthUINT16,
2265     ExplainPcieDeviceControl,
2266     PcieExplainTypeDevice
2267   },
2268   {
2269     STRING_TOKEN (STR_PCIEX_DEVICE_STATUS),
2270     0x0a,
2271     FieldWidthUINT16,
2272     ExplainPcieDeviceStatus,
2273     PcieExplainTypeDevice
2274   },
2275   {
2276     STRING_TOKEN (STR_PCIEX_LINK_CAPABILITIES),
2277     0x0c,
2278     FieldWidthUINT32,
2279     ExplainPcieLinkCap,
2280     PcieExplainTypeLink
2281   },
2282   {
2283     STRING_TOKEN (STR_PCIEX_LINK_CONTROL),
2284     0x10,
2285     FieldWidthUINT16,
2286     ExplainPcieLinkControl,
2287     PcieExplainTypeLink
2288   },
2289   {
2290     STRING_TOKEN (STR_PCIEX_LINK_STATUS),
2291     0x12,
2292     FieldWidthUINT16,
2293     ExplainPcieLinkStatus,
2294     PcieExplainTypeLink
2295   },
2296   {
2297     STRING_TOKEN (STR_PCIEX_SLOT_CAPABILITIES),
2298     0x14,
2299     FieldWidthUINT32,
2300     ExplainPcieSlotCap,
2301     PcieExplainTypeSlot
2302   },
2303   {
2304     STRING_TOKEN (STR_PCIEX_SLOT_CONTROL),
2305     0x18,
2306     FieldWidthUINT16,
2307     ExplainPcieSlotControl,
2308     PcieExplainTypeSlot
2309   },
2310   {
2311     STRING_TOKEN (STR_PCIEX_SLOT_STATUS),
2312     0x1a,
2313     FieldWidthUINT16,
2314     ExplainPcieSlotStatus,
2315     PcieExplainTypeSlot
2316   },
2317   {
2318     STRING_TOKEN (STR_PCIEX_ROOT_CONTROL),
2319     0x1c,
2320     FieldWidthUINT16,
2321     ExplainPcieRootControl,
2322     PcieExplainTypeRoot
2323   },
2324   {
2325     STRING_TOKEN (STR_PCIEX_RSVDP),
2326     0x1e,
2327     FieldWidthUINT16,
2328     ExplainPcieRootCap,
2329     PcieExplainTypeRoot
2330   },
2331   {
2332     STRING_TOKEN (STR_PCIEX_ROOT_STATUS),
2333     0x20,
2334     FieldWidthUINT32,
2335     ExplainPcieRootStatus,
2336     PcieExplainTypeRoot
2337   },
2338   {
2339     0,
2340     0,
2341     (PCIE_CAPREG_FIELD_WIDTH)0,
2342     NULL,
2343     PcieExplainTypeMax
2344   }
2345 };
2346 
2347 //
2348 // Global Variables
2349 //
2350 PCI_CONFIG_SPACE  *mConfigSpace = NULL;
2351 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
2352   {L"-s", TypeValue},
2353   {L"-i", TypeFlag},
2354   {L"-ec", TypeValue},
2355   {NULL, TypeMax}
2356   };
2357 
2358 CHAR16 *DevicePortTypeTable[] = {
2359   L"PCI Express Endpoint",
2360   L"Legacy PCI Express Endpoint",
2361   L"Unknown Type",
2362   L"Unknonw Type",
2363   L"Root Port of PCI Express Root Complex",
2364   L"Upstream Port of PCI Express Switch",
2365   L"Downstream Port of PCI Express Switch",
2366   L"PCI Express to PCI/PCI-X Bridge",
2367   L"PCI/PCI-X to PCI Express Bridge",
2368   L"Root Complex Integrated Endpoint",
2369   L"Root Complex Event Collector"
2370 };
2371 
2372 CHAR16 *L0sLatencyStrTable[] = {
2373   L"Less than 64ns",
2374   L"64ns to less than 128ns",
2375   L"128ns to less than 256ns",
2376   L"256ns to less than 512ns",
2377   L"512ns to less than 1us",
2378   L"1us to less than 2us",
2379   L"2us-4us",
2380   L"More than 4us"
2381 };
2382 
2383 CHAR16 *L1LatencyStrTable[] = {
2384   L"Less than 1us",
2385   L"1us to less than 2us",
2386   L"2us to less than 4us",
2387   L"4us to less than 8us",
2388   L"8us to less than 16us",
2389   L"16us to less than 32us",
2390   L"32us-64us",
2391   L"More than 64us"
2392 };
2393 
2394 CHAR16 *ASPMCtrlStrTable[] = {
2395   L"Disabled",
2396   L"L0s Entry Enabled",
2397   L"L1 Entry Enabled",
2398   L"L0s and L1 Entry Enabled"
2399 };
2400 
2401 CHAR16 *SlotPwrLmtScaleTable[] = {
2402   L"1.0x",
2403   L"0.1x",
2404   L"0.01x",
2405   L"0.001x"
2406 };
2407 
2408 CHAR16 *IndicatorTable[] = {
2409   L"Reserved",
2410   L"On",
2411   L"Blink",
2412   L"Off"
2413 };
2414 
2415 
2416 /**
2417   Function for 'pci' command.
2418 
2419   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
2420   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
2421 **/
2422 SHELL_STATUS
2423 EFIAPI
ShellCommandRunPci(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)2424 ShellCommandRunPci (
2425   IN EFI_HANDLE        ImageHandle,
2426   IN EFI_SYSTEM_TABLE  *SystemTable
2427   )
2428 {
2429   UINT16                            Segment;
2430   UINT16                            Bus;
2431   UINT16                            Device;
2432   UINT16                            Func;
2433   UINT64                            Address;
2434   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *IoDev;
2435   EFI_STATUS                        Status;
2436   PCI_DEVICE_INDEPENDENT_REGION     PciHeader;
2437   PCI_CONFIG_SPACE                  ConfigSpace;
2438   UINTN                             ScreenCount;
2439   UINTN                             TempColumn;
2440   UINTN                             ScreenSize;
2441   BOOLEAN                           ExplainData;
2442   UINTN                             Index;
2443   UINTN                             SizeOfHeader;
2444   BOOLEAN                           PrintTitle;
2445   UINTN                             HandleBufSize;
2446   EFI_HANDLE                        *HandleBuf;
2447   UINTN                             HandleCount;
2448   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
2449   UINT16                            MinBus;
2450   UINT16                            MaxBus;
2451   BOOLEAN                           IsEnd;
2452   LIST_ENTRY                        *Package;
2453   CHAR16                            *ProblemParam;
2454   SHELL_STATUS                      ShellStatus;
2455   CONST CHAR16                      *Temp;
2456   UINT64                            RetVal;
2457   UINT16                            ExtendedCapability;
2458   UINT8                             PcieCapabilityPtr;
2459   UINT8                             *ExtendedConfigSpace;
2460   UINTN                             ExtendedConfigSize;
2461 
2462   ShellStatus         = SHELL_SUCCESS;
2463   Status              = EFI_SUCCESS;
2464   Address             = 0;
2465   IoDev               = NULL;
2466   HandleBuf           = NULL;
2467   Package             = NULL;
2468 
2469   //
2470   // initialize the shell lib (we must be in non-auto-init...)
2471   //
2472   Status = ShellInitialize();
2473   ASSERT_EFI_ERROR(Status);
2474 
2475   Status = CommandInit();
2476   ASSERT_EFI_ERROR(Status);
2477 
2478   //
2479   // parse the command line
2480   //
2481   Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
2482   if (EFI_ERROR(Status)) {
2483     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
2484       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"pci", ProblemParam);
2485       FreePool(ProblemParam);
2486       ShellStatus = SHELL_INVALID_PARAMETER;
2487     } else {
2488       ASSERT(FALSE);
2489     }
2490   } else {
2491 
2492     if (ShellCommandLineGetCount(Package) == 2) {
2493       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"pci");
2494       ShellStatus = SHELL_INVALID_PARAMETER;
2495       goto Done;
2496     }
2497 
2498     if (ShellCommandLineGetCount(Package) > 4) {
2499       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"pci");
2500       ShellStatus = SHELL_INVALID_PARAMETER;
2501       goto Done;
2502     }
2503     if (ShellCommandLineGetFlag(Package, L"-ec") && ShellCommandLineGetValue(Package, L"-ec") == NULL) {
2504       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle,  L"pci", L"-ec");
2505       ShellStatus = SHELL_INVALID_PARAMETER;
2506       goto Done;
2507     }
2508     if (ShellCommandLineGetFlag(Package, L"-s") && ShellCommandLineGetValue(Package, L"-s") == NULL) {
2509       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle,  L"pci", L"-s");
2510       ShellStatus = SHELL_INVALID_PARAMETER;
2511       goto Done;
2512     }
2513     //
2514     // Get all instances of PciRootBridgeIo. Allocate space for 1 EFI_HANDLE and
2515     // call LibLocateHandle(), if EFI_BUFFER_TOO_SMALL is returned, allocate enough
2516     // space for handles and call it again.
2517     //
2518     HandleBufSize = sizeof (EFI_HANDLE);
2519     HandleBuf     = (EFI_HANDLE *) AllocateZeroPool (HandleBufSize);
2520     if (HandleBuf == NULL) {
2521       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"pci");
2522       ShellStatus = SHELL_OUT_OF_RESOURCES;
2523       goto Done;
2524     }
2525 
2526     Status = gBS->LocateHandle (
2527                   ByProtocol,
2528                   &gEfiPciRootBridgeIoProtocolGuid,
2529                   NULL,
2530                   &HandleBufSize,
2531                   HandleBuf
2532                  );
2533 
2534     if (Status == EFI_BUFFER_TOO_SMALL) {
2535       HandleBuf = ReallocatePool (sizeof (EFI_HANDLE), HandleBufSize, HandleBuf);
2536       if (HandleBuf == NULL) {
2537         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"pci");
2538         ShellStatus = SHELL_OUT_OF_RESOURCES;
2539         goto Done;
2540       }
2541 
2542       Status = gBS->LocateHandle (
2543                     ByProtocol,
2544                     &gEfiPciRootBridgeIoProtocolGuid,
2545                     NULL,
2546                     &HandleBufSize,
2547                     HandleBuf
2548                    );
2549     }
2550 
2551     if (EFI_ERROR (Status)) {
2552       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PCIRBIO_NF), gShellDebug1HiiHandle, L"pci");
2553       ShellStatus = SHELL_NOT_FOUND;
2554       goto Done;
2555     }
2556 
2557     HandleCount = HandleBufSize / sizeof (EFI_HANDLE);
2558     //
2559     // Argument Count == 1(no other argument): enumerate all pci functions
2560     //
2561     if (ShellCommandLineGetCount(Package) == 1) {
2562       gST->ConOut->QueryMode (
2563                     gST->ConOut,
2564                     gST->ConOut->Mode->Mode,
2565                     &TempColumn,
2566                     &ScreenSize
2567                    );
2568 
2569       ScreenCount = 0;
2570       ScreenSize -= 4;
2571       if ((ScreenSize & 1) == 1) {
2572         ScreenSize -= 1;
2573       }
2574 
2575       PrintTitle = TRUE;
2576 
2577       //
2578       // For each handle, which decides a segment and a bus number range,
2579       // enumerate all devices on it.
2580       //
2581       for (Index = 0; Index < HandleCount; Index++) {
2582         Status = PciGetProtocolAndResource (
2583                   HandleBuf[Index],
2584                   &IoDev,
2585                   &Descriptors
2586                  );
2587         if (EFI_ERROR (Status)) {
2588           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_HANDLE_CFG_ERR), gShellDebug1HiiHandle, L"pci");
2589           ShellStatus = SHELL_NOT_FOUND;
2590           goto Done;
2591         }
2592         //
2593         // No document say it's impossible for a RootBridgeIo protocol handle
2594         // to have more than one address space descriptors, so find out every
2595         // bus range and for each of them do device enumeration.
2596         //
2597         while (TRUE) {
2598           Status = PciGetNextBusRange (&Descriptors, &MinBus, &MaxBus, &IsEnd);
2599 
2600           if (EFI_ERROR (Status)) {
2601             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_BUS_RANGE_ERR), gShellDebug1HiiHandle, L"pci");
2602             ShellStatus = SHELL_NOT_FOUND;
2603             goto Done;
2604           }
2605 
2606           if (IsEnd) {
2607             break;
2608           }
2609 
2610           for (Bus = MinBus; Bus <= MaxBus; Bus++) {
2611             //
2612             // For each devices, enumerate all functions it contains
2613             //
2614             for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
2615               //
2616               // For each function, read its configuration space and print summary
2617               //
2618               for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
2619                 if (ShellGetExecutionBreakFlag ()) {
2620                   ShellStatus = SHELL_ABORTED;
2621                   goto Done;
2622                 }
2623                 Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
2624                 IoDev->Pci.Read (
2625                             IoDev,
2626                             EfiPciWidthUint16,
2627                             Address,
2628                             1,
2629                             &PciHeader.VendorId
2630                            );
2631 
2632                 //
2633                 // If VendorId = 0xffff, there does not exist a device at this
2634                 // location. For each device, if there is any function on it,
2635                 // there must be 1 function at Function 0. So if Func = 0, there
2636                 // will be no more functions in the same device, so we can break
2637                 // loop to deal with the next device.
2638                 //
2639                 if (PciHeader.VendorId == 0xffff && Func == 0) {
2640                   break;
2641                 }
2642 
2643                 if (PciHeader.VendorId != 0xffff) {
2644 
2645                   if (PrintTitle) {
2646                     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_TITLE), gShellDebug1HiiHandle);
2647                     PrintTitle = FALSE;
2648                   }
2649 
2650                   IoDev->Pci.Read (
2651                               IoDev,
2652                               EfiPciWidthUint32,
2653                               Address,
2654                               sizeof (PciHeader) / sizeof (UINT32),
2655                               &PciHeader
2656                              );
2657 
2658                   ShellPrintHiiEx(
2659                     -1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_P1), gShellDebug1HiiHandle,
2660                     IoDev->SegmentNumber,
2661                     Bus,
2662                     Device,
2663                     Func
2664                    );
2665 
2666                   PciPrintClassCode (PciHeader.ClassCode, FALSE);
2667                   ShellPrintHiiEx(
2668                     -1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_P2), gShellDebug1HiiHandle,
2669                     PciHeader.VendorId,
2670                     PciHeader.DeviceId,
2671                     PciHeader.ClassCode[0]
2672                    );
2673 
2674                   ScreenCount += 2;
2675                   if (ScreenCount >= ScreenSize && ScreenSize != 0) {
2676                     //
2677                     // If ScreenSize == 0 we have the console redirected so don't
2678                     //  block updates
2679                     //
2680                     ScreenCount = 0;
2681                   }
2682                   //
2683                   // If this is not a multi-function device, we can leave the loop
2684                   // to deal with the next device.
2685                   //
2686                   if (Func == 0 && ((PciHeader.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00)) {
2687                     break;
2688                   }
2689                 }
2690               }
2691             }
2692           }
2693           //
2694           // If Descriptor is NULL, Configuration() returns EFI_UNSUPPRORED,
2695           // we assume the bus range is 0~PCI_MAX_BUS. After enumerated all
2696           // devices on all bus, we can leave loop.
2697           //
2698           if (Descriptors == NULL) {
2699             break;
2700           }
2701         }
2702       }
2703 
2704       Status = EFI_SUCCESS;
2705       goto Done;
2706     }
2707 
2708     ExplainData                   = FALSE;
2709     Segment                       = 0;
2710     Bus                           = 0;
2711     Device                        = 0;
2712     Func                          = 0;
2713     ExtendedCapability          = 0xFFFF;
2714     if (ShellCommandLineGetFlag(Package, L"-i")) {
2715       ExplainData = TRUE;
2716     }
2717 
2718     Temp = ShellCommandLineGetValue(Package, L"-s");
2719     if (Temp != NULL) {
2720       //
2721       // Input converted to hexadecimal number.
2722       //
2723       if (!EFI_ERROR (ShellConvertStringToUint64 (Temp, &RetVal, TRUE, TRUE))) {
2724         Segment = (UINT16) RetVal;
2725       } else {
2726         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV_HEX), gShellDebug1HiiHandle, L"pci", Temp);
2727         ShellStatus = SHELL_INVALID_PARAMETER;
2728         goto Done;
2729       }
2730     }
2731 
2732     //
2733     // The first Argument(except "-i") is assumed to be Bus number, second
2734     // to be Device number, and third to be Func number.
2735     //
2736     Temp = ShellCommandLineGetRawValue(Package, 1);
2737     if (Temp != NULL) {
2738       //
2739       // Input converted to hexadecimal number.
2740       //
2741       if (!EFI_ERROR (ShellConvertStringToUint64 (Temp, &RetVal, TRUE, TRUE))) {
2742         Bus = (UINT16) RetVal;
2743       } else {
2744         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV_HEX), gShellDebug1HiiHandle, L"pci", Temp);
2745         ShellStatus = SHELL_INVALID_PARAMETER;
2746         goto Done;
2747       }
2748 
2749       if (Bus > PCI_MAX_BUS) {
2750         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"pci", Temp);
2751         ShellStatus = SHELL_INVALID_PARAMETER;
2752         goto Done;
2753       }
2754     }
2755     Temp = ShellCommandLineGetRawValue(Package, 2);
2756     if (Temp != NULL) {
2757       //
2758       // Input converted to hexadecimal number.
2759       //
2760       if (!EFI_ERROR (ShellConvertStringToUint64 (Temp, &RetVal, TRUE, TRUE))) {
2761         Device = (UINT16) RetVal;
2762       } else {
2763         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV_HEX), gShellDebug1HiiHandle, L"pci", Temp);
2764         ShellStatus = SHELL_INVALID_PARAMETER;
2765         goto Done;
2766       }
2767 
2768       if (Device > PCI_MAX_DEVICE){
2769         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"pci", Temp);
2770         ShellStatus = SHELL_INVALID_PARAMETER;
2771         goto Done;
2772       }
2773     }
2774 
2775     Temp = ShellCommandLineGetRawValue(Package, 3);
2776     if (Temp != NULL) {
2777       //
2778       // Input converted to hexadecimal number.
2779       //
2780       if (!EFI_ERROR (ShellConvertStringToUint64 (Temp, &RetVal, TRUE, TRUE))) {
2781         Func = (UINT16) RetVal;
2782       } else {
2783         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV_HEX), gShellDebug1HiiHandle, L"pci", Temp);
2784         ShellStatus = SHELL_INVALID_PARAMETER;
2785         goto Done;
2786       }
2787 
2788       if (Func > PCI_MAX_FUNC){
2789         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"pci", Temp);
2790         ShellStatus = SHELL_INVALID_PARAMETER;
2791         goto Done;
2792       }
2793     }
2794 
2795     Temp = ShellCommandLineGetValue (Package, L"-ec");
2796     if (Temp != NULL) {
2797       //
2798       // Input converted to hexadecimal number.
2799       //
2800       if (!EFI_ERROR (ShellConvertStringToUint64 (Temp, &RetVal, TRUE, TRUE))) {
2801         ExtendedCapability = (UINT16) RetVal;
2802       } else {
2803         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV_HEX), gShellDebug1HiiHandle, L"pci", Temp);
2804         ShellStatus = SHELL_INVALID_PARAMETER;
2805         goto Done;
2806       }
2807     }
2808 
2809     //
2810     // Find the protocol interface who's in charge of current segment, and its
2811     // bus range covers the current bus
2812     //
2813     Status = PciFindProtocolInterface (
2814               HandleBuf,
2815               HandleCount,
2816               Segment,
2817               Bus,
2818               &IoDev
2819              );
2820 
2821     if (EFI_ERROR (Status)) {
2822       ShellPrintHiiEx(
2823         -1, -1, NULL, STRING_TOKEN (STR_PCI_NO_FIND), gShellDebug1HiiHandle, L"pci",
2824         Segment,
2825         Bus
2826        );
2827       ShellStatus = SHELL_NOT_FOUND;
2828       goto Done;
2829     }
2830 
2831     Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
2832     Status = IoDev->Pci.Read (
2833                           IoDev,
2834                           EfiPciWidthUint8,
2835                           Address,
2836                           sizeof (ConfigSpace),
2837                           &ConfigSpace
2838                          );
2839 
2840     if (EFI_ERROR (Status)) {
2841       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_NO_CFG), gShellDebug1HiiHandle, L"pci");
2842       ShellStatus = SHELL_ACCESS_DENIED;
2843       goto Done;
2844     }
2845 
2846     mConfigSpace = &ConfigSpace;
2847     ShellPrintHiiEx(
2848       -1,
2849       -1,
2850       NULL,
2851       STRING_TOKEN (STR_PCI_INFO),
2852       gShellDebug1HiiHandle,
2853       Segment,
2854       Bus,
2855       Device,
2856       Func,
2857       Segment,
2858       Bus,
2859       Device,
2860       Func
2861      );
2862 
2863     //
2864     // Dump standard header of configuration space
2865     //
2866     SizeOfHeader = sizeof (ConfigSpace.Common) + sizeof (ConfigSpace.NonCommon);
2867 
2868     DumpHex (2, 0, SizeOfHeader, &ConfigSpace);
2869     ShellPrintEx(-1,-1, L"\r\n");
2870 
2871     //
2872     // Dump device dependent Part of configuration space
2873     //
2874     DumpHex (
2875       2,
2876       SizeOfHeader,
2877       sizeof (ConfigSpace) - SizeOfHeader,
2878       ConfigSpace.Data
2879      );
2880 
2881     ExtendedConfigSpace = NULL;
2882     ExtendedConfigSize  = 0;
2883     PcieCapabilityPtr = LocatePciCapability (&ConfigSpace, EFI_PCI_CAPABILITY_ID_PCIEXP);
2884     if (PcieCapabilityPtr != 0) {
2885       ExtendedConfigSize  = 0x1000 - EFI_PCIE_CAPABILITY_BASE_OFFSET;
2886       ExtendedConfigSpace = AllocatePool (ExtendedConfigSize);
2887       if (ExtendedConfigSpace != NULL) {
2888         Status = IoDev->Pci.Read (
2889                               IoDev,
2890                               EfiPciWidthUint32,
2891                               EFI_PCI_ADDRESS (Bus, Device, Func, EFI_PCIE_CAPABILITY_BASE_OFFSET),
2892                               ExtendedConfigSize / sizeof (UINT32),
2893                               ExtendedConfigSpace
2894                               );
2895         if (EFI_ERROR (Status)) {
2896           SHELL_FREE_NON_NULL (ExtendedConfigSpace);
2897         }
2898       }
2899     }
2900 
2901     if ((ExtendedConfigSpace != NULL) && !ShellGetExecutionBreakFlag ()) {
2902       //
2903       // Print the PciEx extend space in raw bytes ( 0xFF-0xFFF)
2904       //
2905       ShellPrintEx (-1, -1, L"\r\n%HStart dumping PCIex extended configuration space (0x100 - 0xFFF).%N\r\n\r\n");
2906 
2907       DumpHex (
2908         2,
2909         EFI_PCIE_CAPABILITY_BASE_OFFSET,
2910         ExtendedConfigSize,
2911         ExtendedConfigSpace
2912         );
2913     }
2914 
2915     //
2916     // If "-i" appears in command line, interpret data in configuration space
2917     //
2918     if (ExplainData) {
2919       PciExplainPci (&ConfigSpace, Address, IoDev);
2920       if ((ExtendedConfigSpace != NULL) && !ShellGetExecutionBreakFlag ()) {
2921         PciExplainPciExpress (
2922           (PCI_CAPABILITY_PCIEXP *) ((UINT8 *) &ConfigSpace + PcieCapabilityPtr),
2923           ExtendedConfigSpace,
2924           ExtendedCapability
2925           );
2926       }
2927     }
2928   }
2929 Done:
2930   if (HandleBuf != NULL) {
2931     FreePool (HandleBuf);
2932   }
2933   if (Package != NULL) {
2934     ShellCommandLineFreeVarList (Package);
2935   }
2936   mConfigSpace = NULL;
2937   return ShellStatus;
2938 }
2939 
2940 /**
2941   This function finds out the protocol which is in charge of the given
2942   segment, and its bus range covers the current bus number. It lookes
2943   each instances of RootBridgeIoProtocol handle, until the one meets the
2944   criteria is found.
2945 
2946   @param[in] HandleBuf       Buffer which holds all PCI_ROOT_BRIDIGE_IO_PROTOCOL handles.
2947   @param[in] HandleCount     Count of all PCI_ROOT_BRIDIGE_IO_PROTOCOL handles.
2948   @param[in] Segment         Segment number of device we are dealing with.
2949   @param[in] Bus             Bus number of device we are dealing with.
2950   @param[out] IoDev          Handle used to access configuration space of PCI device.
2951 
2952   @retval EFI_SUCCESS             The command completed successfully.
2953   @retval EFI_INVALID_PARAMETER   Invalid parameter.
2954 
2955 **/
2956 EFI_STATUS
PciFindProtocolInterface(IN EFI_HANDLE * HandleBuf,IN UINTN HandleCount,IN UINT16 Segment,IN UINT16 Bus,OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL ** IoDev)2957 PciFindProtocolInterface (
2958   IN  EFI_HANDLE                            *HandleBuf,
2959   IN  UINTN                                 HandleCount,
2960   IN  UINT16                                Segment,
2961   IN  UINT16                                Bus,
2962   OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL       **IoDev
2963   )
2964 {
2965   UINTN                             Index;
2966   EFI_STATUS                        Status;
2967   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
2968   UINT16                            MinBus;
2969   UINT16                            MaxBus;
2970   BOOLEAN                           IsEnd;
2971 
2972   //
2973   // Go through all handles, until the one meets the criteria is found
2974   //
2975   for (Index = 0; Index < HandleCount; Index++) {
2976     Status = PciGetProtocolAndResource (HandleBuf[Index], IoDev, &Descriptors);
2977     if (EFI_ERROR (Status)) {
2978       return Status;
2979     }
2980     //
2981     // When Descriptors == NULL, the Configuration() is not implemented,
2982     // so we only check the Segment number
2983     //
2984     if (Descriptors == NULL && Segment == (*IoDev)->SegmentNumber) {
2985       return EFI_SUCCESS;
2986     }
2987 
2988     if ((*IoDev)->SegmentNumber != Segment) {
2989       continue;
2990     }
2991 
2992     while (TRUE) {
2993       Status = PciGetNextBusRange (&Descriptors, &MinBus, &MaxBus, &IsEnd);
2994       if (EFI_ERROR (Status)) {
2995         return Status;
2996       }
2997 
2998       if (IsEnd) {
2999         break;
3000       }
3001 
3002       if (MinBus <= Bus && MaxBus >= Bus) {
3003         return EFI_SUCCESS;
3004       }
3005     }
3006   }
3007 
3008   return EFI_NOT_FOUND;
3009 }
3010 
3011 /**
3012   This function gets the protocol interface from the given handle, and
3013   obtains its address space descriptors.
3014 
3015   @param[in] Handle          The PCI_ROOT_BRIDIGE_IO_PROTOCOL handle.
3016   @param[out] IoDev          Handle used to access configuration space of PCI device.
3017   @param[out] Descriptors    Points to the address space descriptors.
3018 
3019   @retval EFI_SUCCESS     The command completed successfully
3020 **/
3021 EFI_STATUS
PciGetProtocolAndResource(IN EFI_HANDLE Handle,OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL ** IoDev,OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR ** Descriptors)3022 PciGetProtocolAndResource (
3023   IN  EFI_HANDLE                            Handle,
3024   OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL       **IoDev,
3025   OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR     **Descriptors
3026   )
3027 {
3028   EFI_STATUS  Status;
3029 
3030   //
3031   // Get inferface from protocol
3032   //
3033   Status = gBS->HandleProtocol (
3034                 Handle,
3035                 &gEfiPciRootBridgeIoProtocolGuid,
3036                 (VOID**)IoDev
3037                );
3038 
3039   if (EFI_ERROR (Status)) {
3040     return Status;
3041   }
3042   //
3043   // Call Configuration() to get address space descriptors
3044   //
3045   Status = (*IoDev)->Configuration (*IoDev, (VOID**)Descriptors);
3046   if (Status == EFI_UNSUPPORTED) {
3047     *Descriptors = NULL;
3048     return EFI_SUCCESS;
3049 
3050   } else {
3051     return Status;
3052   }
3053 }
3054 
3055 /**
3056   This function get the next bus range of given address space descriptors.
3057   It also moves the pointer backward a node, to get prepared to be called
3058   again.
3059 
3060   @param[in, out] Descriptors Points to current position of a serial of address space
3061                               descriptors.
3062   @param[out] MinBus          The lower range of bus number.
3063   @param[out] MaxBus          The upper range of bus number.
3064   @param[out] IsEnd           Meet end of the serial of descriptors.
3065 
3066   @retval EFI_SUCCESS     The command completed successfully.
3067 **/
3068 EFI_STATUS
PciGetNextBusRange(IN OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR ** Descriptors,OUT UINT16 * MinBus,OUT UINT16 * MaxBus,OUT BOOLEAN * IsEnd)3069 PciGetNextBusRange (
3070   IN OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  **Descriptors,
3071   OUT    UINT16                             *MinBus,
3072   OUT    UINT16                             *MaxBus,
3073   OUT    BOOLEAN                            *IsEnd
3074   )
3075 {
3076   *IsEnd = FALSE;
3077 
3078   //
3079   // When *Descriptors is NULL, Configuration() is not implemented, so assume
3080   // range is 0~PCI_MAX_BUS
3081   //
3082   if ((*Descriptors) == NULL) {
3083     *MinBus = 0;
3084     *MaxBus = PCI_MAX_BUS;
3085     return EFI_SUCCESS;
3086   }
3087   //
3088   // *Descriptors points to one or more address space descriptors, which
3089   // ends with a end tagged descriptor. Examine each of the descriptors,
3090   // if a bus typed one is found and its bus range covers bus, this handle
3091   // is the handle we are looking for.
3092   //
3093 
3094   while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {
3095     if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
3096       *MinBus = (UINT16) (*Descriptors)->AddrRangeMin;
3097       *MaxBus = (UINT16) (*Descriptors)->AddrRangeMax;
3098       (*Descriptors)++;
3099       return (EFI_SUCCESS);
3100     }
3101 
3102     (*Descriptors)++;
3103   }
3104 
3105   if ((*Descriptors)->Desc == ACPI_END_TAG_DESCRIPTOR) {
3106     *IsEnd = TRUE;
3107   }
3108 
3109   return EFI_SUCCESS;
3110 }
3111 
3112 /**
3113   Explain the data in PCI configuration space. The part which is common for
3114   PCI device and bridge is interpreted in this function. It calls other
3115   functions to interpret data unique for device or bridge.
3116 
3117   @param[in] ConfigSpace     Data in PCI configuration space.
3118   @param[in] Address         Address used to access configuration space of this PCI device.
3119   @param[in] IoDev           Handle used to access configuration space of PCI device.
3120 **/
3121 VOID
PciExplainPci(IN PCI_CONFIG_SPACE * ConfigSpace,IN UINT64 Address,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * IoDev)3122 PciExplainPci (
3123   IN PCI_CONFIG_SPACE                       *ConfigSpace,
3124   IN UINT64                                 Address,
3125   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *IoDev
3126   )
3127 {
3128   PCI_DEVICE_INDEPENDENT_REGION *Common;
3129   PCI_HEADER_TYPE               HeaderType;
3130 
3131   Common = &(ConfigSpace->Common);
3132 
3133   ShellPrintEx (-1, -1, L"\r\n");
3134 
3135   //
3136   // Print Vendor Id and Device Id
3137   //
3138   ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_VID_DID), gShellDebug1HiiHandle,
3139     INDEX_OF (&(Common->VendorId)),
3140     Common->VendorId,
3141     INDEX_OF (&(Common->DeviceId)),
3142     Common->DeviceId
3143    );
3144 
3145   //
3146   // Print register Command
3147   //
3148   PciExplainCommand (&(Common->Command));
3149 
3150   //
3151   // Print register Status
3152   //
3153   PciExplainStatus (&(Common->Status), TRUE, PciUndefined);
3154 
3155   //
3156   // Print register Revision ID
3157   //
3158   ShellPrintEx(-1, -1, L"\r\n");
3159   ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_RID), gShellDebug1HiiHandle,
3160     INDEX_OF (&(Common->RevisionID)),
3161     Common->RevisionID
3162    );
3163 
3164   //
3165   // Print register BIST
3166   //
3167   ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_BIST), gShellDebug1HiiHandle, INDEX_OF (&(Common->BIST)));
3168   if ((Common->BIST & BIT7) != 0) {
3169     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_CAP), gShellDebug1HiiHandle, 0x0f & Common->BIST);
3170   } else {
3171     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_CAP_NO), gShellDebug1HiiHandle);
3172   }
3173   //
3174   // Print register Cache Line Size
3175   //
3176   ShellPrintHiiEx(-1, -1, NULL,
3177     STRING_TOKEN (STR_PCI2_CACHE_LINE_SIZE),
3178     gShellDebug1HiiHandle,
3179     INDEX_OF (&(Common->CacheLineSize)),
3180     Common->CacheLineSize
3181    );
3182 
3183   //
3184   // Print register Latency Timer
3185   //
3186   ShellPrintHiiEx(-1, -1, NULL,
3187     STRING_TOKEN (STR_PCI2_LATENCY_TIMER),
3188     gShellDebug1HiiHandle,
3189     INDEX_OF (&(Common->LatencyTimer)),
3190     Common->LatencyTimer
3191    );
3192 
3193   //
3194   // Print register Header Type
3195   //
3196   ShellPrintHiiEx(-1, -1, NULL,
3197     STRING_TOKEN (STR_PCI2_HEADER_TYPE),
3198     gShellDebug1HiiHandle,
3199     INDEX_OF (&(Common->HeaderType)),
3200     Common->HeaderType
3201    );
3202 
3203   if ((Common->HeaderType & BIT7) != 0) {
3204     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_MULTI_FUNCTION), gShellDebug1HiiHandle);
3205 
3206   } else {
3207     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_SINGLE_FUNCTION), gShellDebug1HiiHandle);
3208   }
3209 
3210   HeaderType = (PCI_HEADER_TYPE)(UINT8) (Common->HeaderType & 0x7f);
3211   switch (HeaderType) {
3212   case PciDevice:
3213     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_PCI_DEVICE), gShellDebug1HiiHandle);
3214     break;
3215 
3216   case PciP2pBridge:
3217     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_P2P_BRIDGE), gShellDebug1HiiHandle);
3218     break;
3219 
3220   case PciCardBusBridge:
3221     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_CARDBUS_BRIDGE), gShellDebug1HiiHandle);
3222     break;
3223 
3224   default:
3225     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RESERVED), gShellDebug1HiiHandle);
3226     HeaderType = PciUndefined;
3227   }
3228 
3229   //
3230   // Print register Class Code
3231   //
3232   ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_CLASS), gShellDebug1HiiHandle);
3233   PciPrintClassCode ((UINT8 *) Common->ClassCode, TRUE);
3234   ShellPrintEx (-1, -1, L"\r\n");
3235 }
3236 
3237 /**
3238   Explain the device specific part of data in PCI configuration space.
3239 
3240   @param[in] Device          Data in PCI configuration space.
3241   @param[in] Address         Address used to access configuration space of this PCI device.
3242   @param[in] IoDev           Handle used to access configuration space of PCI device.
3243 
3244   @retval EFI_SUCCESS     The command completed successfully.
3245 **/
3246 EFI_STATUS
PciExplainDeviceData(IN PCI_DEVICE_HEADER_TYPE_REGION * Device,IN UINT64 Address,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * IoDev)3247 PciExplainDeviceData (
3248   IN PCI_DEVICE_HEADER_TYPE_REGION          *Device,
3249   IN UINT64                                 Address,
3250   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *IoDev
3251   )
3252 {
3253   UINTN       Index;
3254   BOOLEAN     BarExist;
3255   EFI_STATUS  Status;
3256   UINTN       BarCount;
3257 
3258   //
3259   // Print Base Address Registers(Bar). When Bar = 0, this Bar does not
3260   // exist. If these no Bar for this function, print "none", otherwise
3261   // list detail information about this Bar.
3262   //
3263   ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BASE_ADDR), gShellDebug1HiiHandle, INDEX_OF (Device->Bar));
3264 
3265   BarExist  = FALSE;
3266   BarCount  = sizeof (Device->Bar) / sizeof (Device->Bar[0]);
3267   for (Index = 0; Index < BarCount; Index++) {
3268     if (Device->Bar[Index] == 0) {
3269       continue;
3270     }
3271 
3272     if (!BarExist) {
3273       BarExist = TRUE;
3274       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_START_TYPE), gShellDebug1HiiHandle);
3275       ShellPrintEx (-1, -1, L"  --------------------------------------------------------------------------");
3276     }
3277 
3278     Status = PciExplainBar (
3279               &(Device->Bar[Index]),
3280               &(mConfigSpace->Common.Command),
3281               Address,
3282               IoDev,
3283               &Index
3284              );
3285 
3286     if (EFI_ERROR (Status)) {
3287       break;
3288     }
3289   }
3290 
3291   if (!BarExist) {
3292     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NONE), gShellDebug1HiiHandle);
3293 
3294   } else {
3295     ShellPrintEx (-1, -1, L"\r\n  --------------------------------------------------------------------------");
3296   }
3297 
3298   //
3299   // Print register Expansion ROM Base Address
3300   //
3301   if ((Device->ExpansionRomBar & BIT0) == 0) {
3302     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_EXPANSION_ROM_DISABLED), gShellDebug1HiiHandle, INDEX_OF (&(Device->ExpansionRomBar)));
3303 
3304   } else {
3305     ShellPrintHiiEx(-1, -1, NULL,
3306       STRING_TOKEN (STR_PCI2_EXPANSION_ROM_BASE),
3307       gShellDebug1HiiHandle,
3308       INDEX_OF (&(Device->ExpansionRomBar)),
3309       Device->ExpansionRomBar
3310      );
3311   }
3312   //
3313   // Print register Cardbus CIS ptr
3314   //
3315   ShellPrintHiiEx(-1, -1, NULL,
3316     STRING_TOKEN (STR_PCI2_CARDBUS_CIS),
3317     gShellDebug1HiiHandle,
3318     INDEX_OF (&(Device->CISPtr)),
3319     Device->CISPtr
3320    );
3321 
3322   //
3323   // Print register Sub-vendor ID and subsystem ID
3324   //
3325   ShellPrintHiiEx(-1, -1, NULL,
3326     STRING_TOKEN (STR_PCI2_SUB_VENDOR_ID),
3327     gShellDebug1HiiHandle,
3328     INDEX_OF (&(Device->SubsystemVendorID)),
3329     Device->SubsystemVendorID
3330    );
3331 
3332   ShellPrintHiiEx(-1, -1, NULL,
3333     STRING_TOKEN (STR_PCI2_SUBSYSTEM_ID),
3334     gShellDebug1HiiHandle,
3335     INDEX_OF (&(Device->SubsystemID)),
3336     Device->SubsystemID
3337    );
3338 
3339   //
3340   // Print register Capabilities Ptr
3341   //
3342   ShellPrintHiiEx(-1, -1, NULL,
3343     STRING_TOKEN (STR_PCI2_CAPABILITIES_PTR),
3344     gShellDebug1HiiHandle,
3345     INDEX_OF (&(Device->CapabilityPtr)),
3346     Device->CapabilityPtr
3347    );
3348 
3349   //
3350   // Print register Interrupt Line and interrupt pin
3351   //
3352   ShellPrintHiiEx(-1, -1, NULL,
3353     STRING_TOKEN (STR_PCI2_INTERRUPT_LINE),
3354     gShellDebug1HiiHandle,
3355     INDEX_OF (&(Device->InterruptLine)),
3356     Device->InterruptLine
3357    );
3358 
3359   ShellPrintHiiEx(-1, -1, NULL,
3360     STRING_TOKEN (STR_PCI2_INTERRUPT_PIN),
3361     gShellDebug1HiiHandle,
3362     INDEX_OF (&(Device->InterruptPin)),
3363     Device->InterruptPin
3364    );
3365 
3366   //
3367   // Print register Min_Gnt and Max_Lat
3368   //
3369   ShellPrintHiiEx(-1, -1, NULL,
3370     STRING_TOKEN (STR_PCI2_MIN_GNT),
3371     gShellDebug1HiiHandle,
3372     INDEX_OF (&(Device->MinGnt)),
3373     Device->MinGnt
3374    );
3375 
3376   ShellPrintHiiEx(-1, -1, NULL,
3377     STRING_TOKEN (STR_PCI2_MAX_LAT),
3378     gShellDebug1HiiHandle,
3379     INDEX_OF (&(Device->MaxLat)),
3380     Device->MaxLat
3381    );
3382 
3383   return EFI_SUCCESS;
3384 }
3385 
3386 /**
3387   Explain the bridge specific part of data in PCI configuration space.
3388 
3389   @param[in] Bridge          Bridge specific data region in PCI configuration space.
3390   @param[in] Address         Address used to access configuration space of this PCI device.
3391   @param[in] IoDev           Handle used to access configuration space of PCI device.
3392 
3393   @retval EFI_SUCCESS     The command completed successfully.
3394 **/
3395 EFI_STATUS
PciExplainBridgeData(IN PCI_BRIDGE_CONTROL_REGISTER * Bridge,IN UINT64 Address,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * IoDev)3396 PciExplainBridgeData (
3397   IN  PCI_BRIDGE_CONTROL_REGISTER           *Bridge,
3398   IN  UINT64                                Address,
3399   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL       *IoDev
3400   )
3401 {
3402   UINTN       Index;
3403   BOOLEAN     BarExist;
3404   UINTN       BarCount;
3405   UINT32      IoAddress32;
3406   EFI_STATUS  Status;
3407 
3408   //
3409   // Print Base Address Registers. When Bar = 0, this Bar does not
3410   // exist. If these no Bar for this function, print "none", otherwise
3411   // list detail information about this Bar.
3412   //
3413   ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BASE_ADDRESS), gShellDebug1HiiHandle, INDEX_OF (&(Bridge->Bar)));
3414 
3415   BarExist  = FALSE;
3416   BarCount  = sizeof (Bridge->Bar) / sizeof (Bridge->Bar[0]);
3417 
3418   for (Index = 0; Index < BarCount; Index++) {
3419     if (Bridge->Bar[Index] == 0) {
3420       continue;
3421     }
3422 
3423     if (!BarExist) {
3424       BarExist = TRUE;
3425       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_START_TYPE_2), gShellDebug1HiiHandle);
3426       ShellPrintEx (-1, -1, L"  --------------------------------------------------------------------------");
3427     }
3428 
3429     Status = PciExplainBar (
3430               &(Bridge->Bar[Index]),
3431               &(mConfigSpace->Common.Command),
3432               Address,
3433               IoDev,
3434               &Index
3435              );
3436 
3437     if (EFI_ERROR (Status)) {
3438       break;
3439     }
3440   }
3441 
3442   if (!BarExist) {
3443     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NONE), gShellDebug1HiiHandle);
3444   } else {
3445     ShellPrintEx (-1, -1, L"\r\n  --------------------------------------------------------------------------");
3446   }
3447 
3448   //
3449   // Expansion register ROM Base Address
3450   //
3451   if ((Bridge->ExpansionRomBAR & BIT0) == 0) {
3452     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NO_EXPANSION_ROM), gShellDebug1HiiHandle, INDEX_OF (&(Bridge->ExpansionRomBAR)));
3453 
3454   } else {
3455     ShellPrintHiiEx(-1, -1, NULL,
3456       STRING_TOKEN (STR_PCI2_EXPANSION_ROM_BASE_2),
3457       gShellDebug1HiiHandle,
3458       INDEX_OF (&(Bridge->ExpansionRomBAR)),
3459       Bridge->ExpansionRomBAR
3460      );
3461   }
3462   //
3463   // Print Bus Numbers(Primary, Secondary, and Subordinate
3464   //
3465   ShellPrintHiiEx(-1, -1, NULL,
3466     STRING_TOKEN (STR_PCI2_BUS_NUMBERS),
3467     gShellDebug1HiiHandle,
3468     INDEX_OF (&(Bridge->PrimaryBus)),
3469     INDEX_OF (&(Bridge->SecondaryBus)),
3470     INDEX_OF (&(Bridge->SubordinateBus))
3471    );
3472 
3473   ShellPrintEx (-1, -1, L"               ------------------------------------------------------\r\n");
3474 
3475   ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BRIDGE), gShellDebug1HiiHandle, Bridge->PrimaryBus);
3476   ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BRIDGE), gShellDebug1HiiHandle, Bridge->SecondaryBus);
3477   ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BRIDGE), gShellDebug1HiiHandle, Bridge->SubordinateBus);
3478 
3479   //
3480   // Print register Secondary Latency Timer
3481   //
3482   ShellPrintHiiEx(-1, -1, NULL,
3483     STRING_TOKEN (STR_PCI2_SECONDARY_TIMER),
3484     gShellDebug1HiiHandle,
3485     INDEX_OF (&(Bridge->SecondaryLatencyTimer)),
3486     Bridge->SecondaryLatencyTimer
3487    );
3488 
3489   //
3490   // Print register Secondary Status
3491   //
3492   PciExplainStatus (&(Bridge->SecondaryStatus), FALSE, PciP2pBridge);
3493 
3494   //
3495   // Print I/O and memory ranges this bridge forwards. There are 3 resource
3496   // types: I/O, memory, and pre-fetchable memory. For each resource type,
3497   // base and limit address are listed.
3498   //
3499   ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RESOURCE_TYPE), gShellDebug1HiiHandle);
3500   ShellPrintEx (-1, -1, L"----------------------------------------------------------------------\r\n");
3501 
3502   //
3503   // IO Base & Limit
3504   //
3505   IoAddress32 = (Bridge->IoBaseUpper16 << 16 | Bridge->IoBase << 8);
3506   IoAddress32 &= 0xfffff000;
3507   ShellPrintHiiEx(-1, -1, NULL,
3508     STRING_TOKEN (STR_PCI2_TWO_VARS),
3509     gShellDebug1HiiHandle,
3510     INDEX_OF (&(Bridge->IoBase)),
3511     IoAddress32
3512    );
3513 
3514   IoAddress32 = (Bridge->IoLimitUpper16 << 16 | Bridge->IoLimit << 8);
3515   IoAddress32 |= 0x00000fff;
3516   ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_ONE_VAR), gShellDebug1HiiHandle, IoAddress32);
3517 
3518   //
3519   // Memory Base & Limit
3520   //
3521   ShellPrintHiiEx(-1, -1, NULL,
3522     STRING_TOKEN (STR_PCI2_MEMORY),
3523     gShellDebug1HiiHandle,
3524     INDEX_OF (&(Bridge->MemoryBase)),
3525     (Bridge->MemoryBase << 16) & 0xfff00000
3526    );
3527 
3528   ShellPrintHiiEx(-1, -1, NULL,
3529     STRING_TOKEN (STR_PCI2_ONE_VAR),
3530     gShellDebug1HiiHandle,
3531     (Bridge->MemoryLimit << 16) | 0x000fffff
3532    );
3533 
3534   //
3535   // Pre-fetch-able Memory Base & Limit
3536   //
3537   ShellPrintHiiEx(-1, -1, NULL,
3538     STRING_TOKEN (STR_PCI2_PREFETCHABLE),
3539     gShellDebug1HiiHandle,
3540     INDEX_OF (&(Bridge->PrefetchableMemoryBase)),
3541     Bridge->PrefetchableBaseUpper32,
3542     (Bridge->PrefetchableMemoryBase << 16) & 0xfff00000
3543    );
3544 
3545   ShellPrintHiiEx(-1, -1, NULL,
3546     STRING_TOKEN (STR_PCI2_TWO_VARS_2),
3547     gShellDebug1HiiHandle,
3548     Bridge->PrefetchableLimitUpper32,
3549     (Bridge->PrefetchableMemoryLimit << 16) | 0x000fffff
3550    );
3551 
3552   //
3553   // Print register Capabilities Pointer
3554   //
3555   ShellPrintHiiEx(-1, -1, NULL,
3556     STRING_TOKEN (STR_PCI2_CAPABILITIES_PTR_2),
3557     gShellDebug1HiiHandle,
3558     INDEX_OF (&(Bridge->CapabilityPtr)),
3559     Bridge->CapabilityPtr
3560    );
3561 
3562   //
3563   // Print register Bridge Control
3564   //
3565   PciExplainBridgeControl (&(Bridge->BridgeControl), PciP2pBridge);
3566 
3567   //
3568   // Print register Interrupt Line & PIN
3569   //
3570   ShellPrintHiiEx(-1, -1, NULL,
3571     STRING_TOKEN (STR_PCI2_INTERRUPT_LINE_2),
3572     gShellDebug1HiiHandle,
3573     INDEX_OF (&(Bridge->InterruptLine)),
3574     Bridge->InterruptLine
3575    );
3576 
3577   ShellPrintHiiEx(-1, -1, NULL,
3578     STRING_TOKEN (STR_PCI2_INTERRUPT_PIN),
3579     gShellDebug1HiiHandle,
3580     INDEX_OF (&(Bridge->InterruptPin)),
3581     Bridge->InterruptPin
3582    );
3583 
3584   return EFI_SUCCESS;
3585 }
3586 
3587 /**
3588   Explain the Base Address Register(Bar) in PCI configuration space.
3589 
3590   @param[in] Bar              Points to the Base Address Register intended to interpret.
3591   @param[in] Command          Points to the register Command.
3592   @param[in] Address          Address used to access configuration space of this PCI device.
3593   @param[in] IoDev            Handle used to access configuration space of PCI device.
3594   @param[in, out] Index       The Index.
3595 
3596   @retval EFI_SUCCESS     The command completed successfully.
3597 **/
3598 EFI_STATUS
PciExplainBar(IN UINT32 * Bar,IN UINT16 * Command,IN UINT64 Address,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * IoDev,IN OUT UINTN * Index)3599 PciExplainBar (
3600   IN UINT32                                 *Bar,
3601   IN UINT16                                 *Command,
3602   IN UINT64                                 Address,
3603   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *IoDev,
3604   IN OUT UINTN                              *Index
3605   )
3606 {
3607   UINT16  OldCommand;
3608   UINT16  NewCommand;
3609   UINT64  Bar64;
3610   UINT32  OldBar32;
3611   UINT32  NewBar32;
3612   UINT64  OldBar64;
3613   UINT64  NewBar64;
3614   BOOLEAN IsMem;
3615   BOOLEAN IsBar32;
3616   UINT64  RegAddress;
3617 
3618   IsBar32   = TRUE;
3619   Bar64     = 0;
3620   NewBar32  = 0;
3621   NewBar64  = 0;
3622 
3623   //
3624   // According the bar type, list detail about this bar, for example: 32 or
3625   // 64 bits; pre-fetchable or not.
3626   //
3627   if ((*Bar & BIT0) == 0) {
3628     //
3629     // This bar is of memory type
3630     //
3631     IsMem = TRUE;
3632 
3633     if ((*Bar & BIT1) == 0 && (*Bar & BIT2) == 0) {
3634       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BAR), gShellDebug1HiiHandle, *Bar & 0xfffffff0);
3635       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_MEM), gShellDebug1HiiHandle);
3636       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_32_BITS), gShellDebug1HiiHandle);
3637 
3638     } else if ((*Bar & BIT1) == 0 && (*Bar & BIT2) != 0) {
3639       Bar64 = 0x0;
3640       CopyMem (&Bar64, Bar, sizeof (UINT64));
3641       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_ONE_VAR_2), gShellDebug1HiiHandle, (UINT32) RShiftU64 ((Bar64 & 0xfffffffffffffff0ULL), 32));
3642       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_ONE_VAR_3), gShellDebug1HiiHandle, (UINT32) (Bar64 & 0xfffffffffffffff0ULL));
3643       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_MEM), gShellDebug1HiiHandle);
3644       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_64_BITS), gShellDebug1HiiHandle);
3645       IsBar32 = FALSE;
3646       *Index += 1;
3647 
3648     } else {
3649       //
3650       // Reserved
3651       //
3652       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BAR), gShellDebug1HiiHandle, *Bar & 0xfffffff0);
3653       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_MEM_2), gShellDebug1HiiHandle);
3654     }
3655 
3656     if ((*Bar & BIT3) == 0) {
3657       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NO), gShellDebug1HiiHandle);
3658 
3659     } else {
3660       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_YES), gShellDebug1HiiHandle);
3661     }
3662 
3663   } else {
3664     //
3665     // This bar is of io type
3666     //
3667     IsMem = FALSE;
3668     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_ONE_VAR_4), gShellDebug1HiiHandle, *Bar & 0xfffffffc);
3669     ShellPrintEx (-1, -1, L"I/O                               ");
3670   }
3671 
3672   //
3673   // Get BAR length(or the amount of resource this bar demands for). To get
3674   // Bar length, first we should temporarily disable I/O and memory access
3675   // of this function(by set bits in the register Command), then write all
3676   // "1"s to this bar. The bar value read back is the amount of resource
3677   // this bar demands for.
3678   //
3679   //
3680   // Disable io & mem access
3681   //
3682   OldCommand  = *Command;
3683   NewCommand  = (UINT16) (OldCommand & 0xfffc);
3684   RegAddress  = Address | INDEX_OF (Command);
3685   IoDev->Pci.Write (IoDev, EfiPciWidthUint16, RegAddress, 1, &NewCommand);
3686 
3687   RegAddress = Address | INDEX_OF (Bar);
3688 
3689   //
3690   // Read after write the BAR to get the size
3691   //
3692   if (IsBar32) {
3693     OldBar32  = *Bar;
3694     NewBar32  = 0xffffffff;
3695 
3696     IoDev->Pci.Write (IoDev, EfiPciWidthUint32, RegAddress, 1, &NewBar32);
3697     IoDev->Pci.Read (IoDev, EfiPciWidthUint32, RegAddress, 1, &NewBar32);
3698     IoDev->Pci.Write (IoDev, EfiPciWidthUint32, RegAddress, 1, &OldBar32);
3699 
3700     if (IsMem) {
3701       NewBar32  = NewBar32 & 0xfffffff0;
3702       NewBar32  = (~NewBar32) + 1;
3703 
3704     } else {
3705       NewBar32  = NewBar32 & 0xfffffffc;
3706       NewBar32  = (~NewBar32) + 1;
3707       NewBar32  = NewBar32 & 0x0000ffff;
3708     }
3709   } else {
3710 
3711     OldBar64 = 0x0;
3712     CopyMem (&OldBar64, Bar, sizeof (UINT64));
3713     NewBar64 = 0xffffffffffffffffULL;
3714 
3715     IoDev->Pci.Write (IoDev, EfiPciWidthUint32, RegAddress, 2, &NewBar64);
3716     IoDev->Pci.Read (IoDev, EfiPciWidthUint32, RegAddress, 2, &NewBar64);
3717     IoDev->Pci.Write (IoDev, EfiPciWidthUint32, RegAddress, 2, &OldBar64);
3718 
3719     if (IsMem) {
3720       NewBar64  = NewBar64 & 0xfffffffffffffff0ULL;
3721       NewBar64  = (~NewBar64) + 1;
3722 
3723     } else {
3724       NewBar64  = NewBar64 & 0xfffffffffffffffcULL;
3725       NewBar64  = (~NewBar64) + 1;
3726       NewBar64  = NewBar64 & 0x000000000000ffff;
3727     }
3728   }
3729   //
3730   // Enable io & mem access
3731   //
3732   RegAddress = Address | INDEX_OF (Command);
3733   IoDev->Pci.Write (IoDev, EfiPciWidthUint16, RegAddress, 1, &OldCommand);
3734 
3735   if (IsMem) {
3736     if (IsBar32) {
3737       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NEWBAR_32), gShellDebug1HiiHandle, NewBar32);
3738       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NEWBAR_32_2), gShellDebug1HiiHandle, NewBar32 + (*Bar & 0xfffffff0) - 1);
3739 
3740     } else {
3741       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RSHIFT), gShellDebug1HiiHandle, (UINT32) RShiftU64 (NewBar64, 32));
3742       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RSHIFT), gShellDebug1HiiHandle, (UINT32) NewBar64);
3743       ShellPrintEx (-1, -1, L"  ");
3744       ShellPrintHiiEx(-1, -1, NULL,
3745         STRING_TOKEN (STR_PCI2_RSHIFT),
3746         gShellDebug1HiiHandle,
3747         (UINT32) RShiftU64 ((NewBar64 + (Bar64 & 0xfffffffffffffff0ULL) - 1), 32)
3748        );
3749       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RSHIFT), gShellDebug1HiiHandle, (UINT32) (NewBar64 + (Bar64 & 0xfffffffffffffff0ULL) - 1));
3750 
3751     }
3752   } else {
3753     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NEWBAR_32_3), gShellDebug1HiiHandle, NewBar32);
3754     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NEWBAR_32_4), gShellDebug1HiiHandle, NewBar32 + (*Bar & 0xfffffffc) - 1);
3755   }
3756 
3757   return EFI_SUCCESS;
3758 }
3759 
3760 /**
3761   Explain the cardbus specific part of data in PCI configuration space.
3762 
3763   @param[in] CardBus         CardBus specific region of PCI configuration space.
3764   @param[in] Address         Address used to access configuration space of this PCI device.
3765   @param[in] IoDev           Handle used to access configuration space of PCI device.
3766 
3767   @retval EFI_SUCCESS     The command completed successfully.
3768 **/
3769 EFI_STATUS
PciExplainCardBusData(IN PCI_CARDBUS_CONTROL_REGISTER * CardBus,IN UINT64 Address,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * IoDev)3770 PciExplainCardBusData (
3771   IN PCI_CARDBUS_CONTROL_REGISTER           *CardBus,
3772   IN UINT64                                 Address,
3773   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *IoDev
3774   )
3775 {
3776   BOOLEAN           Io32Bit;
3777   PCI_CARDBUS_DATA  *CardBusData;
3778 
3779   ShellPrintHiiEx(-1, -1, NULL,
3780     STRING_TOKEN (STR_PCI2_CARDBUS_SOCKET),
3781     gShellDebug1HiiHandle,
3782     INDEX_OF (&(CardBus->CardBusSocketReg)),
3783     CardBus->CardBusSocketReg
3784    );
3785 
3786   //
3787   // Print Secondary Status
3788   //
3789   PciExplainStatus (&(CardBus->SecondaryStatus), FALSE, PciCardBusBridge);
3790 
3791   //
3792   // Print Bus Numbers(Primary bus number, CardBus bus number, and
3793   // Subordinate bus number
3794   //
3795   ShellPrintHiiEx(-1, -1, NULL,
3796     STRING_TOKEN (STR_PCI2_BUS_NUMBERS_2),
3797     gShellDebug1HiiHandle,
3798     INDEX_OF (&(CardBus->PciBusNumber)),
3799     INDEX_OF (&(CardBus->CardBusBusNumber)),
3800     INDEX_OF (&(CardBus->SubordinateBusNumber))
3801    );
3802 
3803   ShellPrintEx (-1, -1, L"               ------------------------------------------------------\r\n");
3804 
3805   ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_CARDBUS), gShellDebug1HiiHandle, CardBus->PciBusNumber);
3806   ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_CARDBUS_2), gShellDebug1HiiHandle, CardBus->CardBusBusNumber);
3807   ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_CARDBUS_3), gShellDebug1HiiHandle, CardBus->SubordinateBusNumber);
3808 
3809   //
3810   // Print CardBus Latency Timer
3811   //
3812   ShellPrintHiiEx(-1, -1, NULL,
3813     STRING_TOKEN (STR_PCI2_CARDBUS_LATENCY),
3814     gShellDebug1HiiHandle,
3815     INDEX_OF (&(CardBus->CardBusLatencyTimer)),
3816     CardBus->CardBusLatencyTimer
3817    );
3818 
3819   //
3820   // Print Memory/Io ranges this cardbus bridge forwards
3821   //
3822   ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RESOURCE_TYPE_2), gShellDebug1HiiHandle);
3823   ShellPrintEx (-1, -1, L"----------------------------------------------------------------------\r\n");
3824 
3825   ShellPrintHiiEx(-1, -1, NULL,
3826     STRING_TOKEN (STR_PCI2_MEM_3),
3827     gShellDebug1HiiHandle,
3828     INDEX_OF (&(CardBus->MemoryBase0)),
3829     CardBus->BridgeControl & BIT8 ? L"    Prefetchable" : L"Non-Prefetchable",
3830     CardBus->MemoryBase0 & 0xfffff000,
3831     CardBus->MemoryLimit0 | 0x00000fff
3832    );
3833 
3834   ShellPrintHiiEx(-1, -1, NULL,
3835     STRING_TOKEN (STR_PCI2_MEM_3),
3836     gShellDebug1HiiHandle,
3837     INDEX_OF (&(CardBus->MemoryBase1)),
3838     CardBus->BridgeControl & BIT9 ? L"    Prefetchable" : L"Non-Prefetchable",
3839     CardBus->MemoryBase1 & 0xfffff000,
3840     CardBus->MemoryLimit1 | 0x00000fff
3841    );
3842 
3843   Io32Bit = (BOOLEAN) (CardBus->IoBase0 & BIT0);
3844   ShellPrintHiiEx(-1, -1, NULL,
3845     STRING_TOKEN (STR_PCI2_IO_2),
3846     gShellDebug1HiiHandle,
3847     INDEX_OF (&(CardBus->IoBase0)),
3848     Io32Bit ? L"          32 bit" : L"          16 bit",
3849     CardBus->IoBase0 & (Io32Bit ? 0xfffffffc : 0x0000fffc),
3850     (CardBus->IoLimit0 & (Io32Bit ? 0xffffffff : 0x0000ffff)) | 0x00000003
3851    );
3852 
3853   Io32Bit = (BOOLEAN) (CardBus->IoBase1 & BIT0);
3854   ShellPrintHiiEx(-1, -1, NULL,
3855     STRING_TOKEN (STR_PCI2_IO_2),
3856     gShellDebug1HiiHandle,
3857     INDEX_OF (&(CardBus->IoBase1)),
3858     Io32Bit ? L"          32 bit" : L"          16 bit",
3859     CardBus->IoBase1 & (Io32Bit ? 0xfffffffc : 0x0000fffc),
3860     (CardBus->IoLimit1 & (Io32Bit ? 0xffffffff : 0x0000ffff)) | 0x00000003
3861    );
3862 
3863   //
3864   // Print register Interrupt Line & PIN
3865   //
3866   ShellPrintHiiEx(-1, -1, NULL,
3867     STRING_TOKEN (STR_PCI2_INTERRUPT_LINE_3),
3868     gShellDebug1HiiHandle,
3869     INDEX_OF (&(CardBus->InterruptLine)),
3870     CardBus->InterruptLine,
3871     INDEX_OF (&(CardBus->InterruptPin)),
3872     CardBus->InterruptPin
3873    );
3874 
3875   //
3876   // Print register Bridge Control
3877   //
3878   PciExplainBridgeControl (&(CardBus->BridgeControl), PciCardBusBridge);
3879 
3880   //
3881   // Print some registers in data region of PCI configuration space for cardbus
3882   // bridge. Fields include: Sub VendorId, Subsystem ID, and Legacy Mode Base
3883   // Address.
3884   //
3885   CardBusData = (PCI_CARDBUS_DATA *) ((UINT8 *) CardBus + sizeof (PCI_CARDBUS_CONTROL_REGISTER));
3886 
3887   ShellPrintHiiEx(-1, -1, NULL,
3888     STRING_TOKEN (STR_PCI2_SUB_VENDOR_ID_2),
3889     gShellDebug1HiiHandle,
3890     INDEX_OF (&(CardBusData->SubVendorId)),
3891     CardBusData->SubVendorId,
3892     INDEX_OF (&(CardBusData->SubSystemId)),
3893     CardBusData->SubSystemId
3894    );
3895 
3896   ShellPrintHiiEx(-1, -1, NULL,
3897     STRING_TOKEN (STR_PCI2_OPTIONAL),
3898     gShellDebug1HiiHandle,
3899     INDEX_OF (&(CardBusData->LegacyBase)),
3900     CardBusData->LegacyBase
3901    );
3902 
3903   return EFI_SUCCESS;
3904 }
3905 
3906 /**
3907   Explain each meaningful bit of register Status. The definition of Status is
3908   slightly different depending on the PCI header type.
3909 
3910   @param[in] Status          Points to the content of register Status.
3911   @param[in] MainStatus      Indicates if this register is main status(not secondary
3912                              status).
3913   @param[in] HeaderType      Header type of this PCI device.
3914 
3915   @retval EFI_SUCCESS     The command completed successfully.
3916 **/
3917 EFI_STATUS
PciExplainStatus(IN UINT16 * Status,IN BOOLEAN MainStatus,IN PCI_HEADER_TYPE HeaderType)3918 PciExplainStatus (
3919   IN UINT16                                 *Status,
3920   IN BOOLEAN                                MainStatus,
3921   IN PCI_HEADER_TYPE                        HeaderType
3922   )
3923 {
3924   if (MainStatus) {
3925     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_STATUS), gShellDebug1HiiHandle, INDEX_OF (Status), *Status);
3926 
3927   } else {
3928     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_SECONDARY_STATUS), gShellDebug1HiiHandle, INDEX_OF (Status), *Status);
3929   }
3930 
3931   ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NEW_CAPABILITIES), gShellDebug1HiiHandle, (*Status & BIT4) != 0);
3932 
3933   //
3934   // Bit 5 is meaningless for CardBus Bridge
3935   //
3936   if (HeaderType == PciCardBusBridge) {
3937     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_66_CAPABLE), gShellDebug1HiiHandle, (*Status & BIT5) != 0);
3938 
3939   } else {
3940     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_66_CAPABLE_2), gShellDebug1HiiHandle, (*Status & BIT5) != 0);
3941   }
3942 
3943   ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_FAST_BACK), gShellDebug1HiiHandle, (*Status & BIT7) != 0);
3944 
3945   ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_MASTER_DATA), gShellDebug1HiiHandle, (*Status & BIT8) != 0);
3946   //
3947   // Bit 9 and bit 10 together decides the DEVSEL timing
3948   //
3949   ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_DEVSEL_TIMING), gShellDebug1HiiHandle);
3950   if ((*Status & BIT9) == 0 && (*Status & BIT10) == 0) {
3951     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_FAST), gShellDebug1HiiHandle);
3952 
3953   } else if ((*Status & BIT9) != 0 && (*Status & BIT10) == 0) {
3954     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_MEDIUM), gShellDebug1HiiHandle);
3955 
3956   } else if ((*Status & BIT9) == 0 && (*Status & BIT10) != 0) {
3957     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_SLOW), gShellDebug1HiiHandle);
3958 
3959   } else {
3960     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RESERVED_2), gShellDebug1HiiHandle);
3961   }
3962 
3963   ShellPrintHiiEx(-1, -1, NULL,
3964     STRING_TOKEN (STR_PCI2_SIGNALED_TARGET),
3965     gShellDebug1HiiHandle,
3966     (*Status & BIT11) != 0
3967    );
3968 
3969   ShellPrintHiiEx(-1, -1, NULL,
3970     STRING_TOKEN (STR_PCI2_RECEIVED_TARGET),
3971     gShellDebug1HiiHandle,
3972     (*Status & BIT12) != 0
3973    );
3974 
3975   ShellPrintHiiEx(-1, -1, NULL,
3976     STRING_TOKEN (STR_PCI2_RECEIVED_MASTER),
3977     gShellDebug1HiiHandle,
3978     (*Status & BIT13) != 0
3979    );
3980 
3981   if (MainStatus) {
3982     ShellPrintHiiEx(-1, -1, NULL,
3983       STRING_TOKEN (STR_PCI2_SIGNALED_ERROR),
3984       gShellDebug1HiiHandle,
3985       (*Status & BIT14) != 0
3986      );
3987 
3988   } else {
3989     ShellPrintHiiEx(-1, -1, NULL,
3990       STRING_TOKEN (STR_PCI2_RECEIVED_ERROR),
3991       gShellDebug1HiiHandle,
3992       (*Status & BIT14) != 0
3993      );
3994   }
3995 
3996   ShellPrintHiiEx(-1, -1, NULL,
3997     STRING_TOKEN (STR_PCI2_DETECTED_ERROR),
3998     gShellDebug1HiiHandle,
3999     (*Status & BIT15) != 0
4000    );
4001 
4002   return EFI_SUCCESS;
4003 }
4004 
4005 /**
4006   Explain each meaningful bit of register Command.
4007 
4008   @param[in] Command         Points to the content of register Command.
4009 
4010   @retval EFI_SUCCESS     The command completed successfully.
4011 **/
4012 EFI_STATUS
PciExplainCommand(IN UINT16 * Command)4013 PciExplainCommand (
4014   IN UINT16                                 *Command
4015   )
4016 {
4017   //
4018   // Print the binary value of register Command
4019   //
4020   ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_COMMAND), gShellDebug1HiiHandle, INDEX_OF (Command), *Command);
4021 
4022   //
4023   // Explain register Command bit by bit
4024   //
4025   ShellPrintHiiEx(-1, -1, NULL,
4026     STRING_TOKEN (STR_PCI2_SPACE_ACCESS_DENIED),
4027     gShellDebug1HiiHandle,
4028     (*Command & BIT0) != 0
4029    );
4030 
4031   ShellPrintHiiEx(-1, -1, NULL,
4032     STRING_TOKEN (STR_PCI2_MEMORY_SPACE),
4033     gShellDebug1HiiHandle,
4034     (*Command & BIT1) != 0
4035    );
4036 
4037   ShellPrintHiiEx(-1, -1, NULL,
4038     STRING_TOKEN (STR_PCI2_BEHAVE_BUS_MASTER),
4039     gShellDebug1HiiHandle,
4040     (*Command & BIT2) != 0
4041    );
4042 
4043   ShellPrintHiiEx(-1, -1, NULL,
4044     STRING_TOKEN (STR_PCI2_MONITOR_SPECIAL_CYCLE),
4045     gShellDebug1HiiHandle,
4046     (*Command & BIT3) != 0
4047    );
4048 
4049   ShellPrintHiiEx(-1, -1, NULL,
4050     STRING_TOKEN (STR_PCI2_MEM_WRITE_INVALIDATE),
4051     gShellDebug1HiiHandle,
4052     (*Command & BIT4) != 0
4053    );
4054 
4055   ShellPrintHiiEx(-1, -1, NULL,
4056     STRING_TOKEN (STR_PCI2_PALETTE_SNOOPING),
4057     gShellDebug1HiiHandle,
4058     (*Command & BIT5) != 0
4059    );
4060 
4061   ShellPrintHiiEx(-1, -1, NULL,
4062     STRING_TOKEN (STR_PCI2_ASSERT_PERR),
4063     gShellDebug1HiiHandle,
4064     (*Command & BIT6) != 0
4065    );
4066 
4067   ShellPrintHiiEx(-1, -1, NULL,
4068     STRING_TOKEN (STR_PCI2_DO_ADDR_STEPPING),
4069     gShellDebug1HiiHandle,
4070     (*Command & BIT7) != 0
4071    );
4072 
4073   ShellPrintHiiEx(-1, -1, NULL,
4074     STRING_TOKEN (STR_PCI2_SERR_DRIVER),
4075     gShellDebug1HiiHandle,
4076     (*Command & BIT8) != 0
4077    );
4078 
4079   ShellPrintHiiEx(-1, -1, NULL,
4080     STRING_TOKEN (STR_PCI2_FAST_BACK_2),
4081     gShellDebug1HiiHandle,
4082     (*Command & BIT9) != 0
4083    );
4084 
4085   return EFI_SUCCESS;
4086 }
4087 
4088 /**
4089   Explain each meaningful bit of register Bridge Control.
4090 
4091   @param[in] BridgeControl   Points to the content of register Bridge Control.
4092   @param[in] HeaderType      The headertype.
4093 
4094   @retval EFI_SUCCESS     The command completed successfully.
4095 **/
4096 EFI_STATUS
PciExplainBridgeControl(IN UINT16 * BridgeControl,IN PCI_HEADER_TYPE HeaderType)4097 PciExplainBridgeControl (
4098   IN UINT16                                 *BridgeControl,
4099   IN PCI_HEADER_TYPE                        HeaderType
4100   )
4101 {
4102   ShellPrintHiiEx(-1, -1, NULL,
4103     STRING_TOKEN (STR_PCI2_BRIDGE_CONTROL),
4104     gShellDebug1HiiHandle,
4105     INDEX_OF (BridgeControl),
4106     *BridgeControl
4107    );
4108 
4109   ShellPrintHiiEx(-1, -1, NULL,
4110     STRING_TOKEN (STR_PCI2_PARITY_ERROR),
4111     gShellDebug1HiiHandle,
4112     (*BridgeControl & BIT0) != 0
4113    );
4114   ShellPrintHiiEx(-1, -1, NULL,
4115     STRING_TOKEN (STR_PCI2_SERR_ENABLE),
4116     gShellDebug1HiiHandle,
4117     (*BridgeControl & BIT1) != 0
4118    );
4119   ShellPrintHiiEx(-1, -1, NULL,
4120     STRING_TOKEN (STR_PCI2_ISA_ENABLE),
4121     gShellDebug1HiiHandle,
4122     (*BridgeControl & BIT2) != 0
4123    );
4124   ShellPrintHiiEx(-1, -1, NULL,
4125     STRING_TOKEN (STR_PCI2_VGA_ENABLE),
4126     gShellDebug1HiiHandle,
4127     (*BridgeControl & BIT3) != 0
4128    );
4129   ShellPrintHiiEx(-1, -1, NULL,
4130     STRING_TOKEN (STR_PCI2_MASTER_ABORT),
4131     gShellDebug1HiiHandle,
4132     (*BridgeControl & BIT5) != 0
4133    );
4134 
4135   //
4136   // Register Bridge Control has some slight differences between P2P bridge
4137   // and Cardbus bridge from bit 6 to bit 11.
4138   //
4139   if (HeaderType == PciP2pBridge) {
4140     ShellPrintHiiEx(-1, -1, NULL,
4141       STRING_TOKEN (STR_PCI2_SECONDARY_BUS_RESET),
4142       gShellDebug1HiiHandle,
4143       (*BridgeControl & BIT6) != 0
4144      );
4145     ShellPrintHiiEx(-1, -1, NULL,
4146       STRING_TOKEN (STR_PCI2_FAST_ENABLE),
4147       gShellDebug1HiiHandle,
4148       (*BridgeControl & BIT7) != 0
4149      );
4150     ShellPrintHiiEx(-1, -1, NULL,
4151       STRING_TOKEN (STR_PCI2_PRIMARY_DISCARD_TIMER),
4152       gShellDebug1HiiHandle,
4153       (*BridgeControl & BIT8)!=0 ? L"2^10" : L"2^15"
4154      );
4155     ShellPrintHiiEx(-1, -1, NULL,
4156       STRING_TOKEN (STR_PCI2_SECONDARY_DISCARD_TIMER),
4157       gShellDebug1HiiHandle,
4158       (*BridgeControl & BIT9)!=0 ? L"2^10" : L"2^15"
4159      );
4160     ShellPrintHiiEx(-1, -1, NULL,
4161       STRING_TOKEN (STR_PCI2_DISCARD_TIMER_STATUS),
4162       gShellDebug1HiiHandle,
4163       (*BridgeControl & BIT10) != 0
4164      );
4165     ShellPrintHiiEx(-1, -1, NULL,
4166       STRING_TOKEN (STR_PCI2_DISCARD_TIMER_SERR),
4167       gShellDebug1HiiHandle,
4168       (*BridgeControl & BIT11) != 0
4169      );
4170 
4171   } else {
4172     ShellPrintHiiEx(-1, -1, NULL,
4173       STRING_TOKEN (STR_PCI2_CARDBUS_RESET),
4174       gShellDebug1HiiHandle,
4175       (*BridgeControl & BIT6) != 0
4176      );
4177     ShellPrintHiiEx(-1, -1, NULL,
4178       STRING_TOKEN (STR_PCI2_IREQ_ENABLE),
4179       gShellDebug1HiiHandle,
4180       (*BridgeControl & BIT7) != 0
4181      );
4182     ShellPrintHiiEx(-1, -1, NULL,
4183       STRING_TOKEN (STR_PCI2_WRITE_POSTING_ENABLE),
4184       gShellDebug1HiiHandle,
4185       (*BridgeControl & BIT10) != 0
4186      );
4187   }
4188 
4189   return EFI_SUCCESS;
4190 }
4191 
4192 /**
4193   Locate capability register block per capability ID.
4194 
4195   @param[in] ConfigSpace       Data in PCI configuration space.
4196   @param[in] CapabilityId      The capability ID.
4197 
4198   @return   The offset of the register block per capability ID,
4199             or 0 if the register block cannot be found.
4200 **/
4201 UINT8
LocatePciCapability(IN PCI_CONFIG_SPACE * ConfigSpace,IN UINT8 CapabilityId)4202 LocatePciCapability (
4203   IN PCI_CONFIG_SPACE   *ConfigSpace,
4204   IN UINT8              CapabilityId
4205   )
4206 {
4207   UINT8                   CapabilityPtr;
4208   EFI_PCI_CAPABILITY_HDR  *CapabilityEntry;
4209 
4210   //
4211   // To check the cpability of this device supports
4212   //
4213   if ((ConfigSpace->Common.Status & EFI_PCI_STATUS_CAPABILITY) == 0) {
4214     return 0;
4215   }
4216 
4217   switch ((PCI_HEADER_TYPE)(ConfigSpace->Common.HeaderType & 0x7f)) {
4218     case PciDevice:
4219       CapabilityPtr = ConfigSpace->NonCommon.Device.CapabilityPtr;
4220       break;
4221     case PciP2pBridge:
4222       CapabilityPtr = ConfigSpace->NonCommon.Bridge.CapabilityPtr;
4223       break;
4224     case PciCardBusBridge:
4225       CapabilityPtr = ConfigSpace->NonCommon.CardBus.Cap_Ptr;
4226       break;
4227     default:
4228       return 0;
4229   }
4230 
4231   while ((CapabilityPtr >= 0x40) && ((CapabilityPtr & 0x03) == 0x00)) {
4232     CapabilityEntry = (EFI_PCI_CAPABILITY_HDR *) ((UINT8 *) ConfigSpace + CapabilityPtr);
4233     if (CapabilityEntry->CapabilityID == CapabilityId) {
4234       return CapabilityPtr;
4235     }
4236 
4237     //
4238     // Certain PCI device may incorrectly have capability pointing to itself,
4239     // break to avoid dead loop.
4240     //
4241     if (CapabilityPtr == CapabilityEntry->NextItemPtr) {
4242       break;
4243     }
4244 
4245     CapabilityPtr = CapabilityEntry->NextItemPtr;
4246   }
4247 
4248   return 0;
4249 }
4250 
4251 /**
4252   Print out information of the capability information.
4253 
4254   @param[in] PciExpressCap  The pointer to the structure about the device.
4255 
4256   @retval EFI_SUCCESS   The operation was successful.
4257 **/
4258 EFI_STATUS
ExplainPcieCapReg(IN PCI_CAPABILITY_PCIEXP * PciExpressCap)4259 ExplainPcieCapReg (
4260   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
4261   )
4262 {
4263   CHAR16 *DevicePortType;
4264 
4265   ShellPrintEx (-1, -1,
4266     L"  Capability Version(3:0):          %E0x%04x%N\r\n",
4267     PciExpressCap->Capability.Bits.Version
4268    );
4269   if (PciExpressCap->Capability.Bits.DevicePortType < ARRAY_SIZE (DevicePortTypeTable)) {
4270     DevicePortType = DevicePortTypeTable[PciExpressCap->Capability.Bits.DevicePortType];
4271   } else {
4272     DevicePortType = L"Unknown Type";
4273   }
4274   ShellPrintEx (-1, -1,
4275     L"  Device/PortType(7:4):             %E%s%N\r\n",
4276     DevicePortType
4277    );
4278   //
4279   // 'Slot Implemented' is only valid for:
4280   // a) Root Port of PCI Express Root Complex, or
4281   // b) Downstream Port of PCI Express Switch
4282   //
4283   if (PciExpressCap->Capability.Bits.DevicePortType== PCIE_DEVICE_PORT_TYPE_ROOT_PORT ||
4284       PciExpressCap->Capability.Bits.DevicePortType == PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT) {
4285     ShellPrintEx (-1, -1,
4286       L"  Slot Implemented(8):              %E%d%N\r\n",
4287       PciExpressCap->Capability.Bits.SlotImplemented
4288      );
4289   }
4290   ShellPrintEx (-1, -1,
4291     L"  Interrupt Message Number(13:9):   %E0x%05x%N\r\n",
4292     PciExpressCap->Capability.Bits.InterruptMessageNumber
4293    );
4294   return EFI_SUCCESS;
4295 }
4296 
4297 /**
4298   Print out information of the device capability information.
4299 
4300   @param[in] PciExpressCap  The pointer to the structure about the device.
4301 
4302   @retval EFI_SUCCESS   The operation was successful.
4303 **/
4304 EFI_STATUS
ExplainPcieDeviceCap(IN PCI_CAPABILITY_PCIEXP * PciExpressCap)4305 ExplainPcieDeviceCap (
4306   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
4307   )
4308 {
4309   UINT8  DevicePortType;
4310   UINT8  L0sLatency;
4311   UINT8  L1Latency;
4312 
4313   DevicePortType = (UINT8)PciExpressCap->Capability.Bits.DevicePortType;
4314   ShellPrintEx (-1, -1, L"  Max_Payload_Size Supported(2:0):          ");
4315   if (PciExpressCap->DeviceCapability.Bits.MaxPayloadSize < 6) {
4316     ShellPrintEx (-1, -1, L"%E%d bytes%N\r\n", 1 << (PciExpressCap->DeviceCapability.Bits.MaxPayloadSize + 7));
4317   } else {
4318     ShellPrintEx (-1, -1, L"%EUnknown%N\r\n");
4319   }
4320   ShellPrintEx (-1, -1,
4321     L"  Phantom Functions Supported(4:3):         %E%d%N\r\n",
4322     PciExpressCap->DeviceCapability.Bits.PhantomFunctions
4323    );
4324   ShellPrintEx (-1, -1,
4325     L"  Extended Tag Field Supported(5):          %E%d-bit Tag field supported%N\r\n",
4326     PciExpressCap->DeviceCapability.Bits.ExtendedTagField ? 8 : 5
4327    );
4328   //
4329   // Endpoint L0s and L1 Acceptable Latency is only valid for Endpoint
4330   //
4331   if (IS_PCIE_ENDPOINT (DevicePortType)) {
4332     L0sLatency = (UINT8)PciExpressCap->DeviceCapability.Bits.EndpointL0sAcceptableLatency;
4333     L1Latency  = (UINT8)PciExpressCap->DeviceCapability.Bits.EndpointL1AcceptableLatency;
4334     ShellPrintEx (-1, -1, L"  Endpoint L0s Acceptable Latency(8:6):     ");
4335     if (L0sLatency < 4) {
4336       ShellPrintEx (-1, -1, L"%EMaximum of %d ns%N\r\n", 1 << (L0sLatency + 6));
4337     } else {
4338       if (L0sLatency < 7) {
4339         ShellPrintEx (-1, -1, L"%EMaximum of %d us%N\r\n", 1 << (L0sLatency - 3));
4340       } else {
4341         ShellPrintEx (-1, -1, L"%ENo limit%N\r\n");
4342       }
4343     }
4344     ShellPrintEx (-1, -1, L"  Endpoint L1 Acceptable Latency(11:9):     ");
4345     if (L1Latency < 7) {
4346       ShellPrintEx (-1, -1, L"%EMaximum of %d us%N\r\n", 1 << (L1Latency + 1));
4347     } else {
4348       ShellPrintEx (-1, -1, L"%ENo limit%N\r\n");
4349     }
4350   }
4351   ShellPrintEx (-1, -1,
4352     L"  Role-based Error Reporting(15):           %E%d%N\r\n",
4353     PciExpressCap->DeviceCapability.Bits.RoleBasedErrorReporting
4354    );
4355   //
4356   // Only valid for Upstream Port:
4357   // a) Captured Slot Power Limit Value
4358   // b) Captured Slot Power Scale
4359   //
4360   if (DevicePortType == PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT) {
4361     ShellPrintEx (-1, -1,
4362       L"  Captured Slot Power Limit Value(25:18):   %E0x%02x%N\r\n",
4363       PciExpressCap->DeviceCapability.Bits.CapturedSlotPowerLimitValue
4364      );
4365     ShellPrintEx (-1, -1,
4366       L"  Captured Slot Power Limit Scale(27:26):   %E%s%N\r\n",
4367       SlotPwrLmtScaleTable[PciExpressCap->DeviceCapability.Bits.CapturedSlotPowerLimitScale]
4368      );
4369   }
4370   //
4371   // Function Level Reset Capability is only valid for Endpoint
4372   //
4373   if (IS_PCIE_ENDPOINT (DevicePortType)) {
4374     ShellPrintEx (-1, -1,
4375       L"  Function Level Reset Capability(28):      %E%d%N\r\n",
4376       PciExpressCap->DeviceCapability.Bits.FunctionLevelReset
4377      );
4378   }
4379   return EFI_SUCCESS;
4380 }
4381 
4382 /**
4383   Print out information of the device control information.
4384 
4385   @param[in] PciExpressCap  The pointer to the structure about the device.
4386 
4387   @retval EFI_SUCCESS   The operation was successful.
4388 **/
4389 EFI_STATUS
ExplainPcieDeviceControl(IN PCI_CAPABILITY_PCIEXP * PciExpressCap)4390 ExplainPcieDeviceControl (
4391   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
4392   )
4393 {
4394   ShellPrintEx (-1, -1,
4395     L"  Correctable Error Reporting Enable(0):    %E%d%N\r\n",
4396     PciExpressCap->DeviceControl.Bits.CorrectableError
4397     );
4398   ShellPrintEx (-1, -1,
4399     L"  Non-Fatal Error Reporting Enable(1):      %E%d%N\r\n",
4400     PciExpressCap->DeviceControl.Bits.NonFatalError
4401    );
4402   ShellPrintEx (-1, -1,
4403     L"  Fatal Error Reporting Enable(2):          %E%d%N\r\n",
4404     PciExpressCap->DeviceControl.Bits.FatalError
4405    );
4406   ShellPrintEx (-1, -1,
4407     L"  Unsupported Request Reporting Enable(3):  %E%d%N\r\n",
4408     PciExpressCap->DeviceControl.Bits.UnsupportedRequest
4409    );
4410   ShellPrintEx (-1, -1,
4411     L"  Enable Relaxed Ordering(4):               %E%d%N\r\n",
4412     PciExpressCap->DeviceControl.Bits.RelaxedOrdering
4413    );
4414   ShellPrintEx (-1, -1, L"  Max_Payload_Size(7:5):                    ");
4415   if (PciExpressCap->DeviceControl.Bits.MaxPayloadSize < 6) {
4416     ShellPrintEx (-1, -1, L"%E%d bytes%N\r\n", 1 << (PciExpressCap->DeviceControl.Bits.MaxPayloadSize + 7));
4417   } else {
4418     ShellPrintEx (-1, -1, L"%EUnknown%N\r\n");
4419   }
4420   ShellPrintEx (-1, -1,
4421     L"  Extended Tag Field Enable(8):             %E%d%N\r\n",
4422     PciExpressCap->DeviceControl.Bits.ExtendedTagField
4423    );
4424   ShellPrintEx (-1, -1,
4425     L"  Phantom Functions Enable(9):              %E%d%N\r\n",
4426     PciExpressCap->DeviceControl.Bits.PhantomFunctions
4427    );
4428   ShellPrintEx (-1, -1,
4429     L"  Auxiliary (AUX) Power PM Enable(10):      %E%d%N\r\n",
4430     PciExpressCap->DeviceControl.Bits.AuxPower
4431    );
4432   ShellPrintEx (-1, -1,
4433     L"  Enable No Snoop(11):                      %E%d%N\r\n",
4434     PciExpressCap->DeviceControl.Bits.NoSnoop
4435    );
4436   ShellPrintEx (-1, -1, L"  Max_Read_Request_Size(14:12):             ");
4437   if (PciExpressCap->DeviceControl.Bits.MaxReadRequestSize < 6) {
4438     ShellPrintEx (-1, -1, L"%E%d bytes%N\r\n", 1 << (PciExpressCap->DeviceControl.Bits.MaxReadRequestSize + 7));
4439   } else {
4440     ShellPrintEx (-1, -1, L"%EUnknown%N\r\n");
4441   }
4442   //
4443   // Read operation is only valid for PCI Express to PCI/PCI-X Bridges
4444   //
4445   if (PciExpressCap->Capability.Bits.DevicePortType == PCIE_DEVICE_PORT_TYPE_PCIE_TO_PCI_BRIDGE) {
4446     ShellPrintEx (-1, -1,
4447       L"  Bridge Configuration Retry Enable(15):  %E%d%N\r\n",
4448       PciExpressCap->DeviceControl.Bits.BridgeConfigurationRetryOrFunctionLevelReset
4449      );
4450   }
4451   return EFI_SUCCESS;
4452 }
4453 
4454 /**
4455   Print out information of the device status information.
4456 
4457   @param[in] PciExpressCap  The pointer to the structure about the device.
4458 
4459   @retval EFI_SUCCESS   The operation was successful.
4460 **/
4461 EFI_STATUS
ExplainPcieDeviceStatus(IN PCI_CAPABILITY_PCIEXP * PciExpressCap)4462 ExplainPcieDeviceStatus (
4463   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
4464   )
4465 {
4466   ShellPrintEx (-1, -1,
4467     L"  Correctable Error Detected(0):            %E%d%N\r\n",
4468     PciExpressCap->DeviceStatus.Bits.CorrectableError
4469    );
4470   ShellPrintEx (-1, -1,
4471     L"  Non-Fatal Error Detected(1):              %E%d%N\r\n",
4472     PciExpressCap->DeviceStatus.Bits.NonFatalError
4473    );
4474   ShellPrintEx (-1, -1,
4475     L"  Fatal Error Detected(2):                  %E%d%N\r\n",
4476     PciExpressCap->DeviceStatus.Bits.FatalError
4477    );
4478   ShellPrintEx (-1, -1,
4479     L"  Unsupported Request Detected(3):          %E%d%N\r\n",
4480     PciExpressCap->DeviceStatus.Bits.UnsupportedRequest
4481    );
4482   ShellPrintEx (-1, -1,
4483     L"  AUX Power Detected(4):                    %E%d%N\r\n",
4484     PciExpressCap->DeviceStatus.Bits.AuxPower
4485    );
4486   ShellPrintEx (-1, -1,
4487     L"  Transactions Pending(5):                  %E%d%N\r\n",
4488     PciExpressCap->DeviceStatus.Bits.TransactionsPending
4489    );
4490   return EFI_SUCCESS;
4491 }
4492 
4493 /**
4494   Print out information of the device link information.
4495 
4496   @param[in] PciExpressCap  The pointer to the structure about the device.
4497 
4498   @retval EFI_SUCCESS   The operation was successful.
4499 **/
4500 EFI_STATUS
ExplainPcieLinkCap(IN PCI_CAPABILITY_PCIEXP * PciExpressCap)4501 ExplainPcieLinkCap (
4502   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
4503   )
4504 {
4505   CHAR16 *MaxLinkSpeed;
4506   CHAR16 *AspmValue;
4507 
4508   switch (PciExpressCap->LinkCapability.Bits.MaxLinkSpeed) {
4509     case 1:
4510       MaxLinkSpeed = L"2.5 GT/s";
4511       break;
4512     case 2:
4513       MaxLinkSpeed = L"5.0 GT/s";
4514       break;
4515     case 3:
4516       MaxLinkSpeed = L"8.0 GT/s";
4517       break;
4518     case 4:
4519       MaxLinkSpeed = L"16.0 GT/s";
4520       break;
4521     case 5:
4522       MaxLinkSpeed = L"32.0 GT/s";
4523       break;
4524     default:
4525       MaxLinkSpeed = L"Reserved";
4526       break;
4527   }
4528   ShellPrintEx (-1, -1,
4529     L"  Maximum Link Speed(3:0):                            %E%s%N\r\n",
4530     MaxLinkSpeed
4531    );
4532   ShellPrintEx (-1, -1,
4533     L"  Maximum Link Width(9:4):                            %Ex%d%N\r\n",
4534     PciExpressCap->LinkCapability.Bits.MaxLinkWidth
4535    );
4536   switch (PciExpressCap->LinkCapability.Bits.Aspm) {
4537     case 0:
4538       AspmValue = L"Not";
4539       break;
4540     case 1:
4541       AspmValue = L"L0s";
4542       break;
4543     case 2:
4544       AspmValue = L"L1";
4545       break;
4546     case 3:
4547       AspmValue = L"L0s and L1";
4548       break;
4549     default:
4550       AspmValue = L"Reserved";
4551       break;
4552   }
4553   ShellPrintEx (-1, -1,
4554     L"  Active State Power Management Support(11:10):       %E%s Supported%N\r\n",
4555     AspmValue
4556    );
4557   ShellPrintEx (-1, -1,
4558     L"  L0s Exit Latency(14:12):                            %E%s%N\r\n",
4559     L0sLatencyStrTable[PciExpressCap->LinkCapability.Bits.L0sExitLatency]
4560    );
4561   ShellPrintEx (-1, -1,
4562     L"  L1 Exit Latency(17:15):                             %E%s%N\r\n",
4563     L1LatencyStrTable[PciExpressCap->LinkCapability.Bits.L1ExitLatency]
4564    );
4565   ShellPrintEx (-1, -1,
4566     L"  Clock Power Management(18):                         %E%d%N\r\n",
4567     PciExpressCap->LinkCapability.Bits.ClockPowerManagement
4568    );
4569   ShellPrintEx (-1, -1,
4570     L"  Surprise Down Error Reporting Capable(19):          %E%d%N\r\n",
4571     PciExpressCap->LinkCapability.Bits.SurpriseDownError
4572    );
4573   ShellPrintEx (-1, -1,
4574     L"  Data Link Layer Link Active Reporting Capable(20):  %E%d%N\r\n",
4575     PciExpressCap->LinkCapability.Bits.DataLinkLayerLinkActive
4576    );
4577   ShellPrintEx (-1, -1,
4578     L"  Link Bandwidth Notification Capability(21):         %E%d%N\r\n",
4579     PciExpressCap->LinkCapability.Bits.LinkBandwidthNotification
4580    );
4581   ShellPrintEx (-1, -1,
4582     L"  Port Number(31:24):                                 %E0x%02x%N\r\n",
4583     PciExpressCap->LinkCapability.Bits.PortNumber
4584    );
4585   return EFI_SUCCESS;
4586 }
4587 
4588 /**
4589   Print out information of the device link control information.
4590 
4591   @param[in] PciExpressCap  The pointer to the structure about the device.
4592 
4593   @retval EFI_SUCCESS   The operation was successful.
4594 **/
4595 EFI_STATUS
ExplainPcieLinkControl(IN PCI_CAPABILITY_PCIEXP * PciExpressCap)4596 ExplainPcieLinkControl (
4597   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
4598   )
4599 {
4600   UINT8  DevicePortType;
4601 
4602   DevicePortType  = (UINT8)PciExpressCap->Capability.Bits.DevicePortType;
4603   ShellPrintEx (-1, -1,
4604     L"  Active State Power Management Control(1:0):         %E%s%N\r\n",
4605     ASPMCtrlStrTable[PciExpressCap->LinkControl.Bits.AspmControl]
4606    );
4607   //
4608   // RCB is not applicable to switches
4609   //
4610   if (!IS_PCIE_SWITCH(DevicePortType)) {
4611     ShellPrintEx (-1, -1,
4612       L"  Read Completion Boundary (RCB)(3):                  %E%d byte%N\r\n",
4613       1 << (PciExpressCap->LinkControl.Bits.ReadCompletionBoundary + 6)
4614      );
4615   }
4616   //
4617   // Link Disable is reserved on
4618   // a) Endpoints
4619   // b) PCI Express to PCI/PCI-X bridges
4620   // c) Upstream Ports of Switches
4621   //
4622   if (!IS_PCIE_ENDPOINT (DevicePortType) &&
4623       DevicePortType != PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT &&
4624       DevicePortType != PCIE_DEVICE_PORT_TYPE_PCIE_TO_PCI_BRIDGE) {
4625     ShellPrintEx (-1, -1,
4626       L"  Link Disable(4):                                    %E%d%N\r\n",
4627       PciExpressCap->LinkControl.Bits.LinkDisable
4628      );
4629   }
4630   ShellPrintEx (-1, -1,
4631     L"  Common Clock Configuration(6):                      %E%d%N\r\n",
4632     PciExpressCap->LinkControl.Bits.CommonClockConfiguration
4633    );
4634   ShellPrintEx (-1, -1,
4635     L"  Extended Synch(7):                                  %E%d%N\r\n",
4636     PciExpressCap->LinkControl.Bits.ExtendedSynch
4637    );
4638   ShellPrintEx (-1, -1,
4639     L"  Enable Clock Power Management(8):                   %E%d%N\r\n",
4640     PciExpressCap->LinkControl.Bits.ClockPowerManagement
4641    );
4642   ShellPrintEx (-1, -1,
4643     L"  Hardware Autonomous Width Disable(9):               %E%d%N\r\n",
4644     PciExpressCap->LinkControl.Bits.HardwareAutonomousWidthDisable
4645    );
4646   ShellPrintEx (-1, -1,
4647     L"  Link Bandwidth Management Interrupt Enable(10):     %E%d%N\r\n",
4648     PciExpressCap->LinkControl.Bits.LinkBandwidthManagementInterrupt
4649    );
4650   ShellPrintEx (-1, -1,
4651     L"  Link Autonomous Bandwidth Interrupt Enable(11):     %E%d%N\r\n",
4652     PciExpressCap->LinkControl.Bits.LinkAutonomousBandwidthInterrupt
4653    );
4654   return EFI_SUCCESS;
4655 }
4656 
4657 /**
4658   Print out information of the device link status information.
4659 
4660   @param[in] PciExpressCap  The pointer to the structure about the device.
4661 
4662   @retval EFI_SUCCESS   The operation was successful.
4663 **/
4664 EFI_STATUS
ExplainPcieLinkStatus(IN PCI_CAPABILITY_PCIEXP * PciExpressCap)4665 ExplainPcieLinkStatus (
4666   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
4667   )
4668 {
4669   CHAR16 *CurLinkSpeed;
4670 
4671   switch (PciExpressCap->LinkStatus.Bits.CurrentLinkSpeed) {
4672     case 1:
4673       CurLinkSpeed = L"2.5 GT/s";
4674       break;
4675     case 2:
4676       CurLinkSpeed = L"5.0 GT/s";
4677       break;
4678     case 3:
4679       CurLinkSpeed = L"8.0 GT/s";
4680       break;
4681     case 4:
4682       CurLinkSpeed = L"16.0 GT/s";
4683       break;
4684     case 5:
4685       CurLinkSpeed = L"32.0 GT/s";
4686       break;
4687     default:
4688       CurLinkSpeed = L"Reserved";
4689       break;
4690   }
4691   ShellPrintEx (-1, -1,
4692     L"  Current Link Speed(3:0):                            %E%s%N\r\n",
4693     CurLinkSpeed
4694    );
4695   ShellPrintEx (-1, -1,
4696     L"  Negotiated Link Width(9:4):                         %Ex%d%N\r\n",
4697     PciExpressCap->LinkStatus.Bits.NegotiatedLinkWidth
4698    );
4699   ShellPrintEx (-1, -1,
4700     L"  Link Training(11):                                  %E%d%N\r\n",
4701     PciExpressCap->LinkStatus.Bits.LinkTraining
4702    );
4703   ShellPrintEx (-1, -1,
4704     L"  Slot Clock Configuration(12):                       %E%d%N\r\n",
4705     PciExpressCap->LinkStatus.Bits.SlotClockConfiguration
4706    );
4707   ShellPrintEx (-1, -1,
4708     L"  Data Link Layer Link Active(13):                    %E%d%N\r\n",
4709     PciExpressCap->LinkStatus.Bits.DataLinkLayerLinkActive
4710    );
4711   ShellPrintEx (-1, -1,
4712     L"  Link Bandwidth Management Status(14):               %E%d%N\r\n",
4713     PciExpressCap->LinkStatus.Bits.LinkBandwidthManagement
4714    );
4715   ShellPrintEx (-1, -1,
4716     L"  Link Autonomous Bandwidth Status(15):               %E%d%N\r\n",
4717     PciExpressCap->LinkStatus.Bits.LinkAutonomousBandwidth
4718    );
4719   return EFI_SUCCESS;
4720 }
4721 
4722 /**
4723   Print out information of the device slot information.
4724 
4725   @param[in] PciExpressCap  The pointer to the structure about the device.
4726 
4727   @retval EFI_SUCCESS   The operation was successful.
4728 **/
4729 EFI_STATUS
ExplainPcieSlotCap(IN PCI_CAPABILITY_PCIEXP * PciExpressCap)4730 ExplainPcieSlotCap (
4731   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
4732   )
4733 {
4734   ShellPrintEx (-1, -1,
4735     L"  Attention Button Present(0):                        %E%d%N\r\n",
4736     PciExpressCap->SlotCapability.Bits.AttentionButton
4737    );
4738   ShellPrintEx (-1, -1,
4739     L"  Power Controller Present(1):                        %E%d%N\r\n",
4740     PciExpressCap->SlotCapability.Bits.PowerController
4741    );
4742   ShellPrintEx (-1, -1,
4743     L"  MRL Sensor Present(2):                              %E%d%N\r\n",
4744     PciExpressCap->SlotCapability.Bits.MrlSensor
4745    );
4746   ShellPrintEx (-1, -1,
4747     L"  Attention Indicator Present(3):                     %E%d%N\r\n",
4748     PciExpressCap->SlotCapability.Bits.AttentionIndicator
4749    );
4750   ShellPrintEx (-1, -1,
4751     L"  Power Indicator Present(4):                         %E%d%N\r\n",
4752     PciExpressCap->SlotCapability.Bits.PowerIndicator
4753    );
4754   ShellPrintEx (-1, -1,
4755     L"  Hot-Plug Surprise(5):                               %E%d%N\r\n",
4756     PciExpressCap->SlotCapability.Bits.HotPlugSurprise
4757    );
4758   ShellPrintEx (-1, -1,
4759     L"  Hot-Plug Capable(6):                                %E%d%N\r\n",
4760     PciExpressCap->SlotCapability.Bits.HotPlugCapable
4761    );
4762   ShellPrintEx (-1, -1,
4763     L"  Slot Power Limit Value(14:7):                       %E0x%02x%N\r\n",
4764     PciExpressCap->SlotCapability.Bits.SlotPowerLimitValue
4765    );
4766   ShellPrintEx (-1, -1,
4767     L"  Slot Power Limit Scale(16:15):                      %E%s%N\r\n",
4768     SlotPwrLmtScaleTable[PciExpressCap->SlotCapability.Bits.SlotPowerLimitScale]
4769    );
4770   ShellPrintEx (-1, -1,
4771     L"  Electromechanical Interlock Present(17):            %E%d%N\r\n",
4772     PciExpressCap->SlotCapability.Bits.ElectromechanicalInterlock
4773    );
4774   ShellPrintEx (-1, -1,
4775     L"  No Command Completed Support(18):                   %E%d%N\r\n",
4776     PciExpressCap->SlotCapability.Bits.NoCommandCompleted
4777    );
4778   ShellPrintEx (-1, -1,
4779     L"  Physical Slot Number(31:19):                        %E%d%N\r\n",
4780     PciExpressCap->SlotCapability.Bits.PhysicalSlotNumber
4781    );
4782 
4783   return EFI_SUCCESS;
4784 }
4785 
4786 /**
4787   Print out information of the device slot control information.
4788 
4789   @param[in] PciExpressCap  The pointer to the structure about the device.
4790 
4791   @retval EFI_SUCCESS   The operation was successful.
4792 **/
4793 EFI_STATUS
ExplainPcieSlotControl(IN PCI_CAPABILITY_PCIEXP * PciExpressCap)4794 ExplainPcieSlotControl (
4795   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
4796   )
4797 {
4798   ShellPrintEx (-1, -1,
4799     L"  Attention Button Pressed Enable(0):                 %E%d%N\r\n",
4800     PciExpressCap->SlotControl.Bits.AttentionButtonPressed
4801    );
4802   ShellPrintEx (-1, -1,
4803     L"  Power Fault Detected Enable(1):                     %E%d%N\r\n",
4804     PciExpressCap->SlotControl.Bits.PowerFaultDetected
4805    );
4806   ShellPrintEx (-1, -1,
4807     L"  MRL Sensor Changed Enable(2):                       %E%d%N\r\n",
4808     PciExpressCap->SlotControl.Bits.MrlSensorChanged
4809    );
4810   ShellPrintEx (-1, -1,
4811     L"  Presence Detect Changed Enable(3):                  %E%d%N\r\n",
4812     PciExpressCap->SlotControl.Bits.PresenceDetectChanged
4813    );
4814   ShellPrintEx (-1, -1,
4815     L"  Command Completed Interrupt Enable(4):              %E%d%N\r\n",
4816     PciExpressCap->SlotControl.Bits.CommandCompletedInterrupt
4817    );
4818   ShellPrintEx (-1, -1,
4819     L"  Hot-Plug Interrupt Enable(5):                       %E%d%N\r\n",
4820     PciExpressCap->SlotControl.Bits.HotPlugInterrupt
4821    );
4822   ShellPrintEx (-1, -1,
4823     L"  Attention Indicator Control(7:6):                   %E%s%N\r\n",
4824     IndicatorTable[
4825     PciExpressCap->SlotControl.Bits.AttentionIndicator]
4826    );
4827   ShellPrintEx (-1, -1,
4828     L"  Power Indicator Control(9:8):                       %E%s%N\r\n",
4829     IndicatorTable[PciExpressCap->SlotControl.Bits.PowerIndicator]
4830    );
4831   ShellPrintEx (-1, -1, L"  Power Controller Control(10):                       %EPower ");
4832   if (
4833     PciExpressCap->SlotControl.Bits.PowerController) {
4834     ShellPrintEx (-1, -1, L"Off%N\r\n");
4835   } else {
4836     ShellPrintEx (-1, -1, L"On%N\r\n");
4837   }
4838   ShellPrintEx (-1, -1,
4839     L"  Electromechanical Interlock Control(11):            %E%d%N\r\n",
4840     PciExpressCap->SlotControl.Bits.ElectromechanicalInterlock
4841    );
4842   ShellPrintEx (-1, -1,
4843     L"  Data Link Layer State Changed Enable(12):           %E%d%N\r\n",
4844     PciExpressCap->SlotControl.Bits.DataLinkLayerStateChanged
4845    );
4846   return EFI_SUCCESS;
4847 }
4848 
4849 /**
4850   Print out information of the device slot status information.
4851 
4852   @param[in] PciExpressCap  The pointer to the structure about the device.
4853 
4854   @retval EFI_SUCCESS   The operation was successful.
4855 **/
4856 EFI_STATUS
ExplainPcieSlotStatus(IN PCI_CAPABILITY_PCIEXP * PciExpressCap)4857 ExplainPcieSlotStatus (
4858   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
4859   )
4860 {
4861   ShellPrintEx (-1, -1,
4862     L"  Attention Button Pressed(0):           %E%d%N\r\n",
4863     PciExpressCap->SlotStatus.Bits.AttentionButtonPressed
4864    );
4865   ShellPrintEx (-1, -1,
4866     L"  Power Fault Detected(1):               %E%d%N\r\n",
4867     PciExpressCap->SlotStatus.Bits.PowerFaultDetected
4868    );
4869   ShellPrintEx (-1, -1,
4870     L"  MRL Sensor Changed(2):                 %E%d%N\r\n",
4871     PciExpressCap->SlotStatus.Bits.MrlSensorChanged
4872    );
4873   ShellPrintEx (-1, -1,
4874     L"  Presence Detect Changed(3):            %E%d%N\r\n",
4875     PciExpressCap->SlotStatus.Bits.PresenceDetectChanged
4876    );
4877   ShellPrintEx (-1, -1,
4878     L"  Command Completed(4):                  %E%d%N\r\n",
4879     PciExpressCap->SlotStatus.Bits.CommandCompleted
4880    );
4881   ShellPrintEx (-1, -1, L"  MRL Sensor State(5):                   %EMRL ");
4882   if (
4883     PciExpressCap->SlotStatus.Bits.MrlSensor) {
4884     ShellPrintEx (-1, -1, L" Opened%N\r\n");
4885   } else {
4886     ShellPrintEx (-1, -1, L" Closed%N\r\n");
4887   }
4888   ShellPrintEx (-1, -1, L"  Presence Detect State(6):              ");
4889   if (
4890     PciExpressCap->SlotStatus.Bits.PresenceDetect) {
4891     ShellPrintEx (-1, -1, L"%ECard Present in slot%N\r\n");
4892   } else {
4893     ShellPrintEx (-1, -1, L"%ESlot Empty%N\r\n");
4894   }
4895   ShellPrintEx (-1, -1, L"  Electromechanical Interlock Status(7): %EElectromechanical Interlock ");
4896   if (
4897     PciExpressCap->SlotStatus.Bits.ElectromechanicalInterlock) {
4898     ShellPrintEx (-1, -1, L"Engaged%N\r\n");
4899   } else {
4900     ShellPrintEx (-1, -1, L"Disengaged%N\r\n");
4901   }
4902   ShellPrintEx (-1, -1,
4903     L"  Data Link Layer State Changed(8):      %E%d%N\r\n",
4904     PciExpressCap->SlotStatus.Bits.DataLinkLayerStateChanged
4905    );
4906   return EFI_SUCCESS;
4907 }
4908 
4909 /**
4910   Print out information of the device root information.
4911 
4912   @param[in] PciExpressCap  The pointer to the structure about the device.
4913 
4914   @retval EFI_SUCCESS   The operation was successful.
4915 **/
4916 EFI_STATUS
ExplainPcieRootControl(IN PCI_CAPABILITY_PCIEXP * PciExpressCap)4917 ExplainPcieRootControl (
4918   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
4919   )
4920 {
4921   ShellPrintEx (-1, -1,
4922     L"  System Error on Correctable Error Enable(0):  %E%d%N\r\n",
4923     PciExpressCap->RootControl.Bits.SystemErrorOnCorrectableError
4924    );
4925   ShellPrintEx (-1, -1,
4926     L"  System Error on Non-Fatal Error Enable(1):    %E%d%N\r\n",
4927     PciExpressCap->RootControl.Bits.SystemErrorOnNonFatalError
4928    );
4929   ShellPrintEx (-1, -1,
4930     L"  System Error on Fatal Error Enable(2):        %E%d%N\r\n",
4931     PciExpressCap->RootControl.Bits.SystemErrorOnFatalError
4932    );
4933   ShellPrintEx (-1, -1,
4934     L"  PME Interrupt Enable(3):                      %E%d%N\r\n",
4935     PciExpressCap->RootControl.Bits.PmeInterrupt
4936    );
4937   ShellPrintEx (-1, -1,
4938     L"  CRS Software Visibility Enable(4):            %E%d%N\r\n",
4939     PciExpressCap->RootControl.Bits.CrsSoftwareVisibility
4940    );
4941 
4942   return EFI_SUCCESS;
4943 }
4944 
4945 /**
4946   Print out information of the device root capability information.
4947 
4948   @param[in] PciExpressCap  The pointer to the structure about the device.
4949 
4950   @retval EFI_SUCCESS   The operation was successful.
4951 **/
4952 EFI_STATUS
ExplainPcieRootCap(IN PCI_CAPABILITY_PCIEXP * PciExpressCap)4953 ExplainPcieRootCap (
4954   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
4955   )
4956 {
4957   ShellPrintEx (-1, -1,
4958     L"  CRS Software Visibility(0):                   %E%d%N\r\n",
4959     PciExpressCap->RootCapability.Bits.CrsSoftwareVisibility
4960    );
4961 
4962   return EFI_SUCCESS;
4963 }
4964 
4965 /**
4966   Print out information of the device root status information.
4967 
4968   @param[in] PciExpressCap  The pointer to the structure about the device.
4969 
4970   @retval EFI_SUCCESS   The operation was successful.
4971 **/
4972 EFI_STATUS
ExplainPcieRootStatus(IN PCI_CAPABILITY_PCIEXP * PciExpressCap)4973 ExplainPcieRootStatus (
4974   IN PCI_CAPABILITY_PCIEXP *PciExpressCap
4975   )
4976 {
4977   ShellPrintEx (-1, -1,
4978     L"  PME Requester ID(15:0):                       %E0x%04x%N\r\n",
4979     PciExpressCap->RootStatus.Bits.PmeRequesterId
4980    );
4981   ShellPrintEx (-1, -1,
4982     L"  PME Status(16):                               %E%d%N\r\n",
4983     PciExpressCap->RootStatus.Bits.PmeStatus
4984    );
4985   ShellPrintEx (-1, -1,
4986     L"  PME Pending(17):                              %E%d%N\r\n",
4987     PciExpressCap->RootStatus.Bits.PmePending
4988    );
4989   return EFI_SUCCESS;
4990 }
4991 
4992 /**
4993   Function to interpret and print out the link control structure
4994 
4995   @param[in] HeaderAddress        The Address of this capability header.
4996   @param[in] HeadersBaseAddress   The address of all the extended capability headers.
4997 **/
4998 EFI_STATUS
PrintInterpretedExtendedCompatibilityLinkControl(IN CONST PCI_EXP_EXT_HDR * HeaderAddress,IN CONST PCI_EXP_EXT_HDR * HeadersBaseAddress)4999 PrintInterpretedExtendedCompatibilityLinkControl (
5000   IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
5001   IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
5002   )
5003 {
5004   CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_INTERNAL_LINK_CONTROL *Header;
5005   Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_INTERNAL_LINK_CONTROL*)HeaderAddress;
5006 
5007   ShellPrintHiiEx(
5008     -1, -1, NULL,
5009     STRING_TOKEN (STR_PCI_EXT_CAP_LINK_CONTROL),
5010     gShellDebug1HiiHandle,
5011     Header->RootComplexLinkCapabilities,
5012     Header->RootComplexLinkControl,
5013     Header->RootComplexLinkStatus
5014     );
5015   DumpHex (
5016     4,
5017     EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
5018     sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_INTERNAL_LINK_CONTROL),
5019     (VOID *) (HeaderAddress)
5020     );
5021   return (EFI_SUCCESS);
5022 }
5023 
5024 /**
5025   Function to interpret and print out the power budgeting structure
5026 
5027   @param[in] HeaderAddress        The Address of this capability header.
5028   @param[in] HeadersBaseAddress   The address of all the extended capability headers.
5029 **/
5030 EFI_STATUS
PrintInterpretedExtendedCompatibilityPowerBudgeting(IN CONST PCI_EXP_EXT_HDR * HeaderAddress,IN CONST PCI_EXP_EXT_HDR * HeadersBaseAddress)5031 PrintInterpretedExtendedCompatibilityPowerBudgeting (
5032   IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
5033   IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
5034   )
5035 {
5036   CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_POWER_BUDGETING *Header;
5037   Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_POWER_BUDGETING*)HeaderAddress;
5038 
5039   ShellPrintHiiEx(
5040     -1, -1, NULL,
5041     STRING_TOKEN (STR_PCI_EXT_CAP_POWER),
5042     gShellDebug1HiiHandle,
5043     Header->DataSelect,
5044     Header->Data,
5045     Header->PowerBudgetCapability
5046     );
5047   DumpHex (
5048     4,
5049     EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
5050     sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_POWER_BUDGETING),
5051     (VOID *) (HeaderAddress)
5052     );
5053   return (EFI_SUCCESS);
5054 }
5055 
5056 /**
5057   Function to interpret and print out the ACS structure
5058 
5059   @param[in] HeaderAddress        The Address of this capability header.
5060   @param[in] HeadersBaseAddress   The address of all the extended capability headers.
5061 **/
5062 EFI_STATUS
PrintInterpretedExtendedCompatibilityAcs(IN CONST PCI_EXP_EXT_HDR * HeaderAddress,IN CONST PCI_EXP_EXT_HDR * HeadersBaseAddress)5063 PrintInterpretedExtendedCompatibilityAcs (
5064   IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
5065   IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
5066   )
5067 {
5068   CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_ACS_EXTENDED  *Header;
5069   UINT16                                                VectorSize;
5070   UINT16                                                LoopCounter;
5071 
5072   Header      = (PCI_EXPRESS_EXTENDED_CAPABILITIES_ACS_EXTENDED*)HeaderAddress;
5073   VectorSize  = 0;
5074 
5075   ShellPrintHiiEx(
5076     -1, -1, NULL,
5077     STRING_TOKEN (STR_PCI_EXT_CAP_ACS),
5078     gShellDebug1HiiHandle,
5079     Header->AcsCapability,
5080     Header->AcsControl
5081     );
5082   if (PCI_EXPRESS_EXTENDED_CAPABILITY_ACS_EXTENDED_GET_EGRES_CONTROL(Header)) {
5083     VectorSize = PCI_EXPRESS_EXTENDED_CAPABILITY_ACS_EXTENDED_GET_EGRES_VECTOR_SIZE(Header);
5084     if (VectorSize == 0) {
5085       VectorSize = 256;
5086     }
5087     for (LoopCounter = 0 ; LoopCounter * 8 < VectorSize ; LoopCounter++) {
5088       ShellPrintHiiEx(
5089         -1, -1, NULL,
5090         STRING_TOKEN (STR_PCI_EXT_CAP_ACS2),
5091         gShellDebug1HiiHandle,
5092         LoopCounter + 1,
5093         Header->EgressControlVectorArray[LoopCounter]
5094         );
5095     }
5096   }
5097   DumpHex (
5098     4,
5099     EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
5100     sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_ACS_EXTENDED) + (VectorSize / 8) - 1,
5101     (VOID *) (HeaderAddress)
5102     );
5103   return (EFI_SUCCESS);
5104 }
5105 
5106 /**
5107   Function to interpret and print out the latency tolerance reporting structure
5108 
5109   @param[in] HeaderAddress        The Address of this capability header.
5110   @param[in] HeadersBaseAddress   The address of all the extended capability headers.
5111 **/
5112 EFI_STATUS
PrintInterpretedExtendedCompatibilityLatencyToleranceReporting(IN CONST PCI_EXP_EXT_HDR * HeaderAddress,IN CONST PCI_EXP_EXT_HDR * HeadersBaseAddress)5113 PrintInterpretedExtendedCompatibilityLatencyToleranceReporting (
5114   IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
5115   IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
5116   )
5117 {
5118   CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_LATENCE_TOLERANCE_REPORTING *Header;
5119   Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_LATENCE_TOLERANCE_REPORTING*)HeaderAddress;
5120 
5121   ShellPrintHiiEx(
5122     -1, -1, NULL,
5123     STRING_TOKEN (STR_PCI_EXT_CAP_LAT),
5124     gShellDebug1HiiHandle,
5125     Header->MaxSnoopLatency,
5126     Header->MaxNoSnoopLatency
5127     );
5128   DumpHex (
5129     4,
5130     EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
5131     sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_LATENCE_TOLERANCE_REPORTING),
5132     (VOID *) (HeaderAddress)
5133     );
5134   return (EFI_SUCCESS);
5135 }
5136 
5137 /**
5138   Function to interpret and print out the serial number structure
5139 
5140   @param[in] HeaderAddress        The Address of this capability header.
5141   @param[in] HeadersBaseAddress   The address of all the extended capability headers.
5142 **/
5143 EFI_STATUS
PrintInterpretedExtendedCompatibilitySerialNumber(IN CONST PCI_EXP_EXT_HDR * HeaderAddress,IN CONST PCI_EXP_EXT_HDR * HeadersBaseAddress)5144 PrintInterpretedExtendedCompatibilitySerialNumber (
5145   IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
5146   IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
5147   )
5148 {
5149   CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_SERIAL_NUMBER *Header;
5150   Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_SERIAL_NUMBER*)HeaderAddress;
5151 
5152   ShellPrintHiiEx(
5153     -1, -1, NULL,
5154     STRING_TOKEN (STR_PCI_EXT_CAP_SN),
5155     gShellDebug1HiiHandle,
5156     Header->SerialNumber
5157     );
5158   DumpHex (
5159     4,
5160     EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
5161     sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_SERIAL_NUMBER),
5162     (VOID *) (HeaderAddress)
5163     );
5164   return (EFI_SUCCESS);
5165 }
5166 
5167 /**
5168   Function to interpret and print out the RCRB structure
5169 
5170   @param[in] HeaderAddress        The Address of this capability header.
5171   @param[in] HeadersBaseAddress   The address of all the extended capability headers.
5172 **/
5173 EFI_STATUS
PrintInterpretedExtendedCompatibilityRcrb(IN CONST PCI_EXP_EXT_HDR * HeaderAddress,IN CONST PCI_EXP_EXT_HDR * HeadersBaseAddress)5174 PrintInterpretedExtendedCompatibilityRcrb (
5175   IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
5176   IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
5177   )
5178 {
5179   CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_RCRB_HEADER *Header;
5180   Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_RCRB_HEADER*)HeaderAddress;
5181 
5182   ShellPrintHiiEx(
5183     -1, -1, NULL,
5184     STRING_TOKEN (STR_PCI_EXT_CAP_RCRB),
5185     gShellDebug1HiiHandle,
5186     Header->VendorId,
5187     Header->DeviceId,
5188     Header->RcrbCapabilities,
5189     Header->RcrbControl
5190     );
5191   DumpHex (
5192     4,
5193     EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
5194     sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_RCRB_HEADER),
5195     (VOID *) (HeaderAddress)
5196     );
5197   return (EFI_SUCCESS);
5198 }
5199 
5200 /**
5201   Function to interpret and print out the vendor specific structure
5202 
5203   @param[in] HeaderAddress        The Address of this capability header.
5204   @param[in] HeadersBaseAddress   The address of all the extended capability headers.
5205 **/
5206 EFI_STATUS
PrintInterpretedExtendedCompatibilityVendorSpecific(IN CONST PCI_EXP_EXT_HDR * HeaderAddress,IN CONST PCI_EXP_EXT_HDR * HeadersBaseAddress)5207 PrintInterpretedExtendedCompatibilityVendorSpecific (
5208   IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
5209   IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
5210   )
5211 {
5212   CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_VENDOR_SPECIFIC *Header;
5213   Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_VENDOR_SPECIFIC*)HeaderAddress;
5214 
5215   ShellPrintHiiEx(
5216     -1, -1, NULL,
5217     STRING_TOKEN (STR_PCI_EXT_CAP_VEN),
5218     gShellDebug1HiiHandle,
5219     Header->VendorSpecificHeader
5220     );
5221   DumpHex (
5222     4,
5223     EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
5224     PCI_EXPRESS_EXTENDED_CAPABILITY_VENDOR_SPECIFIC_GET_SIZE(Header),
5225     (VOID *) (HeaderAddress)
5226     );
5227   return (EFI_SUCCESS);
5228 }
5229 
5230 /**
5231   Function to interpret and print out the Event Collector Endpoint Association structure
5232 
5233   @param[in] HeaderAddress        The Address of this capability header.
5234   @param[in] HeadersBaseAddress   The address of all the extended capability headers.
5235 **/
5236 EFI_STATUS
PrintInterpretedExtendedCompatibilityECEA(IN CONST PCI_EXP_EXT_HDR * HeaderAddress,IN CONST PCI_EXP_EXT_HDR * HeadersBaseAddress)5237 PrintInterpretedExtendedCompatibilityECEA (
5238   IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
5239   IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
5240   )
5241 {
5242   CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_EVENT_COLLECTOR_ENDPOINT_ASSOCIATION *Header;
5243   Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_EVENT_COLLECTOR_ENDPOINT_ASSOCIATION*)HeaderAddress;
5244 
5245   ShellPrintHiiEx(
5246     -1, -1, NULL,
5247     STRING_TOKEN (STR_PCI_EXT_CAP_ECEA),
5248     gShellDebug1HiiHandle,
5249     Header->AssociationBitmap
5250     );
5251   DumpHex (
5252     4,
5253     EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
5254     sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_EVENT_COLLECTOR_ENDPOINT_ASSOCIATION),
5255     (VOID *) (HeaderAddress)
5256     );
5257   return (EFI_SUCCESS);
5258 }
5259 
5260 /**
5261   Function to interpret and print out the ARI structure
5262 
5263   @param[in] HeaderAddress        The Address of this capability header.
5264   @param[in] HeadersBaseAddress   The address of all the extended capability headers.
5265 **/
5266 EFI_STATUS
PrintInterpretedExtendedCompatibilityAri(IN CONST PCI_EXP_EXT_HDR * HeaderAddress,IN CONST PCI_EXP_EXT_HDR * HeadersBaseAddress)5267 PrintInterpretedExtendedCompatibilityAri (
5268   IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
5269   IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
5270   )
5271 {
5272   CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_ARI_CAPABILITY *Header;
5273   Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_ARI_CAPABILITY*)HeaderAddress;
5274 
5275   ShellPrintHiiEx(
5276     -1, -1, NULL,
5277     STRING_TOKEN (STR_PCI_EXT_CAP_ARI),
5278     gShellDebug1HiiHandle,
5279     Header->AriCapability,
5280     Header->AriControl
5281     );
5282   DumpHex (
5283     4,
5284     EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
5285     sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_ARI_CAPABILITY),
5286     (VOID *) (HeaderAddress)
5287     );
5288   return (EFI_SUCCESS);
5289 }
5290 
5291 /**
5292   Function to interpret and print out the DPA structure
5293 
5294   @param[in] HeaderAddress        The Address of this capability header.
5295   @param[in] HeadersBaseAddress   The address of all the extended capability headers.
5296 **/
5297 EFI_STATUS
PrintInterpretedExtendedCompatibilityDynamicPowerAllocation(IN CONST PCI_EXP_EXT_HDR * HeaderAddress,IN CONST PCI_EXP_EXT_HDR * HeadersBaseAddress)5298 PrintInterpretedExtendedCompatibilityDynamicPowerAllocation (
5299   IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
5300   IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
5301   )
5302 {
5303   CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_DYNAMIC_POWER_ALLOCATION *Header;
5304   UINT8                                                            LinkCount;
5305   Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_DYNAMIC_POWER_ALLOCATION*)HeaderAddress;
5306 
5307   ShellPrintHiiEx(
5308     -1, -1, NULL,
5309     STRING_TOKEN (STR_PCI_EXT_CAP_DPA),
5310     gShellDebug1HiiHandle,
5311     Header->DpaCapability,
5312     Header->DpaLatencyIndicator,
5313     Header->DpaStatus,
5314     Header->DpaControl
5315     );
5316   for (LinkCount = 0 ; LinkCount < PCI_EXPRESS_EXTENDED_CAPABILITY_DYNAMIC_POWER_ALLOCATION_GET_SUBSTATE_MAX(Header) + 1 ; LinkCount++) {
5317     ShellPrintHiiEx(
5318       -1, -1, NULL,
5319       STRING_TOKEN (STR_PCI_EXT_CAP_DPA2),
5320       gShellDebug1HiiHandle,
5321       LinkCount+1,
5322       Header->DpaPowerAllocationArray[LinkCount]
5323       );
5324   }
5325   DumpHex (
5326     4,
5327     EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
5328     sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_DYNAMIC_POWER_ALLOCATION) - 1 + PCI_EXPRESS_EXTENDED_CAPABILITY_DYNAMIC_POWER_ALLOCATION_GET_SUBSTATE_MAX(Header),
5329     (VOID *) (HeaderAddress)
5330     );
5331   return (EFI_SUCCESS);
5332 }
5333 
5334 /**
5335   Function to interpret and print out the link declaration structure
5336 
5337   @param[in] HeaderAddress        The Address of this capability header.
5338   @param[in] HeadersBaseAddress   The address of all the extended capability headers.
5339 **/
5340 EFI_STATUS
PrintInterpretedExtendedCompatibilityLinkDeclaration(IN CONST PCI_EXP_EXT_HDR * HeaderAddress,IN CONST PCI_EXP_EXT_HDR * HeadersBaseAddress)5341 PrintInterpretedExtendedCompatibilityLinkDeclaration (
5342   IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
5343   IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
5344   )
5345 {
5346   CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_LINK_DECLARATION  *Header;
5347   UINT8                                                     LinkCount;
5348   Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_LINK_DECLARATION*)HeaderAddress;
5349 
5350   ShellPrintHiiEx(
5351     -1, -1, NULL,
5352     STRING_TOKEN (STR_PCI_EXT_CAP_LINK_DECLAR),
5353     gShellDebug1HiiHandle,
5354     Header->ElementSelfDescription
5355     );
5356 
5357   for (LinkCount = 0 ; LinkCount < PCI_EXPRESS_EXTENDED_CAPABILITY_LINK_DECLARATION_GET_LINK_COUNT(Header) ; LinkCount++) {
5358     ShellPrintHiiEx(
5359       -1, -1, NULL,
5360       STRING_TOKEN (STR_PCI_EXT_CAP_LINK_DECLAR2),
5361       gShellDebug1HiiHandle,
5362       LinkCount+1,
5363       Header->LinkEntry[LinkCount]
5364       );
5365   }
5366   DumpHex (
5367     4,
5368     EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
5369     sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_LINK_DECLARATION) + (PCI_EXPRESS_EXTENDED_CAPABILITY_LINK_DECLARATION_GET_LINK_COUNT(Header)-1)*sizeof(UINT32),
5370     (VOID *) (HeaderAddress)
5371     );
5372   return (EFI_SUCCESS);
5373 }
5374 
5375 /**
5376   Function to interpret and print out the Advanced Error Reporting structure
5377 
5378   @param[in] HeaderAddress        The Address of this capability header.
5379   @param[in] HeadersBaseAddress   The address of all the extended capability headers.
5380 **/
5381 EFI_STATUS
PrintInterpretedExtendedCompatibilityAer(IN CONST PCI_EXP_EXT_HDR * HeaderAddress,IN CONST PCI_EXP_EXT_HDR * HeadersBaseAddress)5382 PrintInterpretedExtendedCompatibilityAer (
5383   IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
5384   IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
5385   )
5386 {
5387   CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_ADVANCED_ERROR_REPORTING *Header;
5388   Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_ADVANCED_ERROR_REPORTING*)HeaderAddress;
5389 
5390   ShellPrintHiiEx(
5391     -1, -1, NULL,
5392     STRING_TOKEN (STR_PCI_EXT_CAP_AER),
5393     gShellDebug1HiiHandle,
5394     Header->UncorrectableErrorStatus,
5395     Header->UncorrectableErrorMask,
5396     Header->UncorrectableErrorSeverity,
5397     Header->CorrectableErrorStatus,
5398     Header->CorrectableErrorMask,
5399     Header->AdvancedErrorCapabilitiesAndControl,
5400     Header->HeaderLog[0],
5401     Header->HeaderLog[1],
5402     Header->HeaderLog[2],
5403     Header->HeaderLog[3],
5404     Header->RootErrorCommand,
5405     Header->RootErrorStatus,
5406     Header->ErrorSourceIdentification,
5407     Header->CorrectableErrorSourceIdentification,
5408     Header->TlpPrefixLog[0],
5409     Header->TlpPrefixLog[1],
5410     Header->TlpPrefixLog[2],
5411     Header->TlpPrefixLog[3]
5412     );
5413   DumpHex (
5414     4,
5415     EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
5416     sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_ADVANCED_ERROR_REPORTING),
5417     (VOID *) (HeaderAddress)
5418     );
5419   return (EFI_SUCCESS);
5420 }
5421 
5422 /**
5423   Function to interpret and print out the multicast structure
5424 
5425   @param[in] HeaderAddress        The Address of this capability header.
5426   @param[in] HeadersBaseAddress   The address of all the extended capability headers.
5427   @param[in] PciExpressCapPtr     The address of the PCIe capabilities structure.
5428 **/
5429 EFI_STATUS
PrintInterpretedExtendedCompatibilityMulticast(IN CONST PCI_EXP_EXT_HDR * HeaderAddress,IN CONST PCI_EXP_EXT_HDR * HeadersBaseAddress,IN CONST PCI_CAPABILITY_PCIEXP * PciExpressCapPtr)5430 PrintInterpretedExtendedCompatibilityMulticast (
5431   IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
5432   IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress,
5433   IN CONST PCI_CAPABILITY_PCIEXP *PciExpressCapPtr
5434   )
5435 {
5436   CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_MULTICAST *Header;
5437   Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_MULTICAST*)HeaderAddress;
5438 
5439   ShellPrintHiiEx(
5440     -1, -1, NULL,
5441     STRING_TOKEN (STR_PCI_EXT_CAP_MULTICAST),
5442     gShellDebug1HiiHandle,
5443     Header->MultiCastCapability,
5444     Header->MulticastControl,
5445     Header->McBaseAddress,
5446     Header->McReceiveAddress,
5447     Header->McBlockAll,
5448     Header->McBlockUntranslated,
5449     Header->McOverlayBar
5450     );
5451 
5452   DumpHex (
5453     4,
5454     EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
5455     sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_MULTICAST),
5456     (VOID *) (HeaderAddress)
5457     );
5458 
5459   return (EFI_SUCCESS);
5460 }
5461 
5462 /**
5463   Function to interpret and print out the virtual channel and multi virtual channel structure
5464 
5465   @param[in] HeaderAddress        The Address of this capability header.
5466   @param[in] HeadersBaseAddress   The address of all the extended capability headers.
5467 **/
5468 EFI_STATUS
PrintInterpretedExtendedCompatibilityVirtualChannel(IN CONST PCI_EXP_EXT_HDR * HeaderAddress,IN CONST PCI_EXP_EXT_HDR * HeadersBaseAddress)5469 PrintInterpretedExtendedCompatibilityVirtualChannel (
5470   IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
5471   IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
5472   )
5473 {
5474   CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_VIRTUAL_CHANNEL_CAPABILITY  *Header;
5475   CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_VIRTUAL_CHANNEL_VC          *CapabilityItem;
5476   UINT32                                                              ItemCount;
5477   Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_VIRTUAL_CHANNEL_CAPABILITY*)HeaderAddress;
5478 
5479   ShellPrintHiiEx(
5480     -1, -1, NULL,
5481     STRING_TOKEN (STR_PCI_EXT_CAP_VC_BASE),
5482     gShellDebug1HiiHandle,
5483     Header->ExtendedVcCount,
5484     Header->PortVcCapability1,
5485     Header->PortVcCapability2,
5486     Header->VcArbTableOffset,
5487     Header->PortVcControl,
5488     Header->PortVcStatus
5489     );
5490   for (ItemCount = 0 ; ItemCount < Header->ExtendedVcCount ; ItemCount++) {
5491     CapabilityItem = &Header->Capability[ItemCount];
5492     ShellPrintHiiEx(
5493       -1, -1, NULL,
5494       STRING_TOKEN (STR_PCI_EXT_CAP_VC_ITEM),
5495       gShellDebug1HiiHandle,
5496       ItemCount+1,
5497       CapabilityItem->VcResourceCapability,
5498       CapabilityItem->PortArbTableOffset,
5499       CapabilityItem->VcResourceControl,
5500       CapabilityItem->VcResourceStatus
5501       );
5502   }
5503 
5504   DumpHex (
5505     4,
5506     EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
5507     sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_VIRTUAL_CHANNEL_CAPABILITY)
5508     + Header->ExtendedVcCount * sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_VIRTUAL_CHANNEL_VC),
5509     (VOID *) (HeaderAddress)
5510     );
5511 
5512   return (EFI_SUCCESS);
5513 }
5514 
5515 /**
5516   Function to interpret and print out the resizeable bar structure
5517 
5518   @param[in] HeaderAddress        The Address of this capability header.
5519   @param[in] HeadersBaseAddress   The address of all the extended capability headers.
5520 **/
5521 EFI_STATUS
PrintInterpretedExtendedCompatibilityResizeableBar(IN CONST PCI_EXP_EXT_HDR * HeaderAddress,IN CONST PCI_EXP_EXT_HDR * HeadersBaseAddress)5522 PrintInterpretedExtendedCompatibilityResizeableBar (
5523   IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
5524   IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
5525   )
5526 {
5527   CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR        *Header;
5528   UINT32                                                       ItemCount;
5529   Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR*)HeaderAddress;
5530 
5531   for (ItemCount = 0 ; ItemCount < (UINT32)GET_NUMBER_RESIZABLE_BARS(Header) ; ItemCount++) {
5532     ShellPrintHiiEx(
5533       -1, -1, NULL,
5534       STRING_TOKEN (STR_PCI_EXT_CAP_RESIZE_BAR),
5535       gShellDebug1HiiHandle,
5536       ItemCount+1,
5537       Header->Capability[ItemCount].ResizableBarCapability.Uint32,
5538       Header->Capability[ItemCount].ResizableBarControl.Uint32
5539       );
5540   }
5541 
5542   DumpHex (
5543     4,
5544     EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
5545     (UINT32)GET_NUMBER_RESIZABLE_BARS(Header) * sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY),
5546     (VOID *) (HeaderAddress)
5547     );
5548 
5549   return (EFI_SUCCESS);
5550 }
5551 
5552 /**
5553   Function to interpret and print out the TPH structure
5554 
5555   @param[in] HeaderAddress        The Address of this capability header.
5556   @param[in] HeadersBaseAddress   The address of all the extended capability headers.
5557 **/
5558 EFI_STATUS
PrintInterpretedExtendedCompatibilityTph(IN CONST PCI_EXP_EXT_HDR * HeaderAddress,IN CONST PCI_EXP_EXT_HDR * HeadersBaseAddress)5559 PrintInterpretedExtendedCompatibilityTph (
5560   IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
5561   IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
5562   )
5563 {
5564   CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_TPH *Header;
5565   Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_TPH*)HeaderAddress;
5566 
5567   ShellPrintHiiEx(
5568     -1, -1, NULL,
5569     STRING_TOKEN (STR_PCI_EXT_CAP_TPH),
5570     gShellDebug1HiiHandle,
5571     Header->TphRequesterCapability,
5572     Header->TphRequesterControl
5573     );
5574   DumpHex (
5575     8,
5576     EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)Header->TphStTable - (UINT8*)HeadersBaseAddress),
5577     GET_TPH_TABLE_SIZE(Header),
5578     (VOID *)Header->TphStTable
5579     );
5580 
5581   DumpHex (
5582     4,
5583     EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
5584     sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_TPH) + GET_TPH_TABLE_SIZE(Header) - sizeof(UINT16),
5585     (VOID *) (HeaderAddress)
5586     );
5587 
5588   return (EFI_SUCCESS);
5589 }
5590 
5591 /**
5592   Function to interpret and print out the secondary PCIe capability structure
5593 
5594   @param[in] HeaderAddress        The Address of this capability header.
5595   @param[in] HeadersBaseAddress   The address of all the extended capability headers.
5596   @param[in] PciExpressCapPtr     The address of the PCIe capabilities structure.
5597 **/
5598 EFI_STATUS
PrintInterpretedExtendedCompatibilitySecondary(IN CONST PCI_EXP_EXT_HDR * HeaderAddress,IN CONST PCI_EXP_EXT_HDR * HeadersBaseAddress,IN CONST PCI_CAPABILITY_PCIEXP * PciExpressCap)5599 PrintInterpretedExtendedCompatibilitySecondary (
5600   IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
5601   IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress,
5602   IN CONST PCI_CAPABILITY_PCIEXP *PciExpressCap
5603   )
5604 {
5605   CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_SECONDARY_PCIE *Header;
5606   Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_SECONDARY_PCIE*)HeaderAddress;
5607 
5608   ShellPrintHiiEx(
5609     -1, -1, NULL,
5610     STRING_TOKEN (STR_PCI_EXT_CAP_SECONDARY),
5611     gShellDebug1HiiHandle,
5612     Header->LinkControl3.Uint32,
5613     Header->LaneErrorStatus
5614     );
5615   DumpHex (
5616     8,
5617     EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)Header->EqualizationControl - (UINT8*)HeadersBaseAddress),
5618     PciExpressCap->LinkCapability.Bits.MaxLinkWidth * sizeof (PCI_EXPRESS_REG_LANE_EQUALIZATION_CONTROL),
5619     (VOID *)Header->EqualizationControl
5620     );
5621 
5622   DumpHex (
5623     4,
5624     EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
5625     sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_SECONDARY_PCIE) - sizeof (Header->EqualizationControl)
5626       + PciExpressCap->LinkCapability.Bits.MaxLinkWidth * sizeof (PCI_EXPRESS_REG_LANE_EQUALIZATION_CONTROL),
5627     (VOID *) (HeaderAddress)
5628     );
5629 
5630   return (EFI_SUCCESS);
5631 }
5632 
5633 /**
5634   Display Pcie extended capability details
5635 
5636   @param[in] HeadersBaseAddress   The address of all the extended capability headers.
5637   @param[in] HeaderAddress        The address of this capability header.
5638   @param[in] PciExpressCapPtr     The address of the PCIe capabilities structure.
5639 **/
5640 EFI_STATUS
PrintPciExtendedCapabilityDetails(IN CONST PCI_EXP_EXT_HDR * HeadersBaseAddress,IN CONST PCI_EXP_EXT_HDR * HeaderAddress,IN CONST PCI_CAPABILITY_PCIEXP * PciExpressCapPtr)5641 PrintPciExtendedCapabilityDetails(
5642   IN CONST PCI_EXP_EXT_HDR    *HeadersBaseAddress,
5643   IN CONST PCI_EXP_EXT_HDR    *HeaderAddress,
5644   IN CONST PCI_CAPABILITY_PCIEXP *PciExpressCapPtr
5645   )
5646 {
5647   switch (HeaderAddress->CapabilityId){
5648     case PCI_EXPRESS_EXTENDED_CAPABILITY_ADVANCED_ERROR_REPORTING_ID:
5649       return PrintInterpretedExtendedCompatibilityAer(HeaderAddress, HeadersBaseAddress);
5650     case PCI_EXPRESS_EXTENDED_CAPABILITY_LINK_CONTROL_ID:
5651       return PrintInterpretedExtendedCompatibilityLinkControl(HeaderAddress, HeadersBaseAddress);
5652     case PCI_EXPRESS_EXTENDED_CAPABILITY_LINK_DECLARATION_ID:
5653       return PrintInterpretedExtendedCompatibilityLinkDeclaration(HeaderAddress, HeadersBaseAddress);
5654     case PCI_EXPRESS_EXTENDED_CAPABILITY_SERIAL_NUMBER_ID:
5655       return PrintInterpretedExtendedCompatibilitySerialNumber(HeaderAddress, HeadersBaseAddress);
5656     case PCI_EXPRESS_EXTENDED_CAPABILITY_POWER_BUDGETING_ID:
5657       return PrintInterpretedExtendedCompatibilityPowerBudgeting(HeaderAddress, HeadersBaseAddress);
5658     case PCI_EXPRESS_EXTENDED_CAPABILITY_ACS_EXTENDED_ID:
5659       return PrintInterpretedExtendedCompatibilityAcs(HeaderAddress, HeadersBaseAddress);
5660     case PCI_EXPRESS_EXTENDED_CAPABILITY_LATENCE_TOLERANCE_REPORTING_ID:
5661       return PrintInterpretedExtendedCompatibilityLatencyToleranceReporting(HeaderAddress, HeadersBaseAddress);
5662     case PCI_EXPRESS_EXTENDED_CAPABILITY_ARI_CAPABILITY_ID:
5663       return PrintInterpretedExtendedCompatibilityAri(HeaderAddress, HeadersBaseAddress);
5664     case PCI_EXPRESS_EXTENDED_CAPABILITY_RCRB_HEADER_ID:
5665       return PrintInterpretedExtendedCompatibilityRcrb(HeaderAddress, HeadersBaseAddress);
5666     case PCI_EXPRESS_EXTENDED_CAPABILITY_VENDOR_SPECIFIC_ID:
5667       return PrintInterpretedExtendedCompatibilityVendorSpecific(HeaderAddress, HeadersBaseAddress);
5668     case PCI_EXPRESS_EXTENDED_CAPABILITY_DYNAMIC_POWER_ALLOCATION_ID:
5669       return PrintInterpretedExtendedCompatibilityDynamicPowerAllocation(HeaderAddress, HeadersBaseAddress);
5670     case PCI_EXPRESS_EXTENDED_CAPABILITY_EVENT_COLLECTOR_ENDPOINT_ASSOCIATION_ID:
5671       return PrintInterpretedExtendedCompatibilityECEA(HeaderAddress, HeadersBaseAddress);
5672     case PCI_EXPRESS_EXTENDED_CAPABILITY_VIRTUAL_CHANNEL_ID:
5673     case PCI_EXPRESS_EXTENDED_CAPABILITY_MULTI_FUNCTION_VIRTUAL_CHANNEL_ID:
5674       return PrintInterpretedExtendedCompatibilityVirtualChannel(HeaderAddress, HeadersBaseAddress);
5675     case PCI_EXPRESS_EXTENDED_CAPABILITY_MULTICAST_ID:
5676       //
5677       // should only be present if PCIE_CAP_DEVICEPORT_TYPE(PciExpressCapPtr->PcieCapReg) == 0100b, 0101b, or 0110b
5678       //
5679       return PrintInterpretedExtendedCompatibilityMulticast(HeaderAddress, HeadersBaseAddress, PciExpressCapPtr);
5680     case PCI_EXPRESS_EXTENDED_CAPABILITY_RESIZABLE_BAR_ID:
5681       return PrintInterpretedExtendedCompatibilityResizeableBar(HeaderAddress, HeadersBaseAddress);
5682     case PCI_EXPRESS_EXTENDED_CAPABILITY_TPH_ID:
5683       return PrintInterpretedExtendedCompatibilityTph(HeaderAddress, HeadersBaseAddress);
5684     case PCI_EXPRESS_EXTENDED_CAPABILITY_SECONDARY_PCIE_ID:
5685       return PrintInterpretedExtendedCompatibilitySecondary(HeaderAddress, HeadersBaseAddress, PciExpressCapPtr);
5686     default:
5687       ShellPrintEx (-1, -1,
5688         L"Unknown PCIe extended capability ID (%04xh).  No interpretation available.\r\n",
5689         HeaderAddress->CapabilityId
5690         );
5691       return EFI_SUCCESS;
5692   };
5693 
5694 }
5695 
5696 /**
5697   Display Pcie device structure.
5698 
5699   @param[in] PciExpressCap       PCI Express capability buffer.
5700   @param[in] ExtendedConfigSpace PCI Express extended configuration space.
5701   @param[in] ExtendedCapability  PCI Express extended capability ID to explain.
5702 **/
5703 VOID
PciExplainPciExpress(IN PCI_CAPABILITY_PCIEXP * PciExpressCap,IN UINT8 * ExtendedConfigSpace,IN CONST UINT16 ExtendedCapability)5704 PciExplainPciExpress (
5705   IN  PCI_CAPABILITY_PCIEXP                  *PciExpressCap,
5706   IN  UINT8                                  *ExtendedConfigSpace,
5707   IN CONST UINT16                            ExtendedCapability
5708   )
5709 {
5710   UINT8                 DevicePortType;
5711   UINTN                 Index;
5712   UINT8                 *RegAddr;
5713   UINTN                 RegValue;
5714   PCI_EXP_EXT_HDR       *ExtHdr;
5715 
5716   DevicePortType = (UINT8)PciExpressCap->Capability.Bits.DevicePortType;
5717 
5718   ShellPrintEx (-1, -1, L"\r\nPci Express device capability structure:\r\n");
5719 
5720   for (Index = 0; PcieExplainList[Index].Type < PcieExplainTypeMax; Index++) {
5721     if (ShellGetExecutionBreakFlag()) {
5722       return;
5723     }
5724     RegAddr = (UINT8 *) PciExpressCap + PcieExplainList[Index].Offset;
5725     switch (PcieExplainList[Index].Width) {
5726       case FieldWidthUINT8:
5727         RegValue = *(UINT8 *) RegAddr;
5728         break;
5729       case FieldWidthUINT16:
5730         RegValue = *(UINT16 *) RegAddr;
5731         break;
5732       case FieldWidthUINT32:
5733         RegValue = *(UINT32 *) RegAddr;
5734         break;
5735       default:
5736         RegValue = 0;
5737         break;
5738     }
5739     ShellPrintHiiEx(-1, -1, NULL,
5740       PcieExplainList[Index].Token,
5741       gShellDebug1HiiHandle,
5742       PcieExplainList[Index].Offset,
5743       RegValue
5744      );
5745     if (PcieExplainList[Index].Func == NULL) {
5746       continue;
5747     }
5748     switch (PcieExplainList[Index].Type) {
5749       case PcieExplainTypeLink:
5750         //
5751         // Link registers should not be used by
5752         // a) Root Complex Integrated Endpoint
5753         // b) Root Complex Event Collector
5754         //
5755         if (DevicePortType == PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT ||
5756             DevicePortType == PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_EVENT_COLLECTOR) {
5757           continue;
5758         }
5759         break;
5760       case PcieExplainTypeSlot:
5761         //
5762         // Slot registers are only valid for
5763         // a) Root Port of PCI Express Root Complex
5764         // b) Downstream Port of PCI Express Switch
5765         // and when SlotImplemented bit is set in PCIE cap register.
5766         //
5767         if ((DevicePortType != PCIE_DEVICE_PORT_TYPE_ROOT_PORT &&
5768              DevicePortType != PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT) ||
5769              !PciExpressCap->Capability.Bits.SlotImplemented) {
5770           continue;
5771         }
5772         break;
5773       case PcieExplainTypeRoot:
5774         //
5775         // Root registers are only valid for
5776         // Root Port of PCI Express Root Complex
5777         //
5778         if (DevicePortType != PCIE_DEVICE_PORT_TYPE_ROOT_PORT) {
5779           continue;
5780         }
5781         break;
5782       default:
5783         break;
5784     }
5785     PcieExplainList[Index].Func (PciExpressCap);
5786   }
5787 
5788   ExtHdr = (PCI_EXP_EXT_HDR*)ExtendedConfigSpace;
5789   while (ExtHdr->CapabilityId != 0 && ExtHdr->CapabilityVersion != 0) {
5790     //
5791     // Process this item
5792     //
5793     if (ExtendedCapability == 0xFFFF || ExtendedCapability == ExtHdr->CapabilityId) {
5794       //
5795       // Print this item
5796       //
5797       PrintPciExtendedCapabilityDetails((PCI_EXP_EXT_HDR*)ExtendedConfigSpace, ExtHdr, PciExpressCap);
5798     }
5799 
5800     //
5801     // Advance to the next item if it exists
5802     //
5803     if (ExtHdr->NextCapabilityOffset != 0) {
5804       ExtHdr = (PCI_EXP_EXT_HDR*)(ExtendedConfigSpace + ExtHdr->NextCapabilityOffset - EFI_PCIE_CAPABILITY_BASE_OFFSET);
5805     } else {
5806       break;
5807     }
5808   }
5809 }
5810