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