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