1 /**
2   @file
3   Display the memory type range registers
4 
5   Copyright (c) 2012, Intel Corporation
6   All rights reserved. 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 <WebServer.h>
17 #include <Library/MtrrLib.h>
18 
19 #define VARIABLE_MTRR_VALID     0x800
20 
21 CONST char * mMemoryType [ ] = {
22   "Uncached",
23   "Write Combining",
24   "Reserved",
25   "Reserved",
26   "Write Through",
27   "Write Protected",
28   "Writeback"
29 };
30 
31 
32 /**
33   Display a fixed MTRR row
34 
35   @param [in] SocketFD      The socket's file descriptor to add to the list.
36   @param [in] pPort         The WSDT_PORT structure address
37   @param [in] Start         Start address for the region
38   @param [in] End           End address for the region
39   @param [in] Type          Memory type
40 
41   @retval EFI_SUCCESS       The request was successfully processed
42 
43 **/
44 EFI_STATUS
MtrrDisplayFixedRow(IN int SocketFD,IN WSDT_PORT * pPort,IN UINT64 Start,IN UINT64 End,IN UINT64 Type)45 MtrrDisplayFixedRow (
46   IN int SocketFD,
47   IN WSDT_PORT * pPort,
48   IN UINT64 Start,
49   IN UINT64 End,
50   IN UINT64 Type
51   )
52 {
53   EFI_STATUS Status;
54 
55   //
56   //  Use break instead of goto
57   //
58   for ( ; ; ) {
59     //
60     //  Start the row
61     //
62     Status = HttpSendAnsiString ( SocketFD,
63                                   pPort,
64                                   "  <tr><td align=\"right\"><code>0x" );
65     if ( EFI_ERROR ( Status )) {
66       break;
67     }
68 
69     //
70     //  Start
71     //
72     Status = HttpSendHexValue ( SocketFD,
73                                 pPort,
74                                 Start );
75     if ( EFI_ERROR ( Status )) {
76       break;
77     }
78 
79     //
80     //  End
81     //
82     Status = HttpSendAnsiString ( SocketFD,
83                                   pPort,
84                                   "</code></td><td align=\"right\"><code>0x" );
85     if ( EFI_ERROR ( Status )) {
86       break;
87     }
88     Status = HttpSendHexValue ( SocketFD,
89                                 pPort,
90                                 End - 1 );
91     if ( EFI_ERROR ( Status )) {
92       break;
93     }
94 
95     //
96     //  Type
97     //
98     Status = HttpSendAnsiString ( SocketFD,
99                                   pPort,
100                                   "</code></td><td>" );
101     if ( EFI_ERROR ( Status )) {
102       break;
103     }
104     Type &= 0xff;
105     Status = HttpSendAnsiString ( SocketFD,
106                                   pPort,
107                                   ( DIM ( mMemoryType ) > Type )
108                                   ? mMemoryType [ Type ]
109                                   : "Reserved" );
110     if ( EFI_ERROR ( Status )) {
111       break;
112     }
113 
114     //
115     //  End of row
116     //
117     Status = HttpSendAnsiString ( SocketFD,
118                                   pPort,
119                                   "</td></tr>\r\n" );
120     break;
121   }
122 
123   //
124   //  Return the final status
125   //
126   return Status;
127 }
128 
129 
130 /**
131   Display the memory type registers
132 
133   @param [in] SocketFD      The socket's file descriptor to add to the list.
134   @param [in] pPort         The WSDT_PORT structure address
135   @param [out] pbDone       Address to receive the request completion status
136 
137   @retval EFI_SUCCESS       The request was successfully processed
138 
139 **/
140 EFI_STATUS
MemoryTypeRegistersPage(IN int SocketFD,IN WSDT_PORT * pPort,OUT BOOLEAN * pbDone)141 MemoryTypeRegistersPage (
142   IN int SocketFD,
143   IN WSDT_PORT * pPort,
144   OUT BOOLEAN * pbDone
145   )
146 {
147   UINT64 Addr;
148   BOOLEAN bValid;
149   UINT64 Capabilities;
150   UINTN Count;
151   UINT64 DefType;
152   UINTN Index;
153   UINT64 Mask;
154   UINT64 MaxMtrrs;
155   CONST UINT64 mFixedAddresses [( 8 * MTRR_NUMBER_OF_FIXED_MTRR ) + 1 ] = {
156            0ULL,
157      0x10000ULL,
158      0x20000ULL,
159      0x30000ULL,
160      0x40000ULL,
161      0x50000ULL,
162      0x60000ULL,
163      0x70000ULL,
164 
165      0x80000ULL,
166      0x84000ULL,
167      0x88000ULL,
168      0x8c000ULL,
169      0x90000ULL,
170      0x94000ULL,
171      0x98000ULL,
172      0x9c000ULL,
173 
174      0xa0000ULL,
175      0xa4000ULL,
176      0xa8000ULL,
177      0xac000ULL,
178      0xb0000ULL,
179      0xb4000ULL,
180      0xb8000ULL,
181      0xbc000ULL,
182 
183      0xc0000ULL,
184      0xc1000ULL,
185      0xc2000ULL,
186      0xc3000ULL,
187      0xc4000ULL,
188      0xc5000ULL,
189      0xc6000ULL,
190      0xc7000ULL,
191 
192      0xc8000ULL,
193      0xc9000ULL,
194      0xca000ULL,
195      0xcb000ULL,
196      0xcc000ULL,
197      0xcd000ULL,
198      0xce000ULL,
199      0xcf000ULL,
200 
201      0xd0000ULL,
202      0xd1000ULL,
203      0xd2000ULL,
204      0xd3000ULL,
205      0xd4000ULL,
206      0xd5000ULL,
207      0xd6000ULL,
208      0xd7000ULL,
209 
210      0xd8000ULL,
211      0xd9000ULL,
212      0xda000ULL,
213      0xdb000ULL,
214      0xdc000ULL,
215      0xdd000ULL,
216      0xde000ULL,
217      0xdf000ULL,
218 
219      0xe0000ULL,
220      0xe1000ULL,
221      0xe2000ULL,
222      0xe3000ULL,
223      0xe4000ULL,
224      0xe5000ULL,
225      0xe6000ULL,
226      0xe7000ULL,
227 
228      0xe8000ULL,
229      0xe9000ULL,
230      0xea000ULL,
231      0xeb000ULL,
232      0xec000ULL,
233      0xed000ULL,
234      0xee000ULL,
235      0xef000ULL,
236 
237      0xf0000ULL,
238      0xf1000ULL,
239      0xf2000ULL,
240      0xf3000ULL,
241      0xf4000ULL,
242      0xf5000ULL,
243      0xf6000ULL,
244      0xf7000ULL,
245 
246      0xf8000ULL,
247      0xf9000ULL,
248      0xfa000ULL,
249      0xfb000ULL,
250      0xfc000ULL,
251      0xfd000ULL,
252      0xfe000ULL,
253      0xff000ULL,
254 
255     0x100000ULL
256   };
257   MTRR_SETTINGS Mtrr;
258   CONST UINT64 * pMemEnd;
259   CONST UINT64 * pMemStart;
260   UINT64 PreviousType;
261   UINT64 ShiftCount;
262   EFI_STATUS Status;
263   UINT64 Type;
264   INT64 Value;
265 
266   DBG_ENTER ( );
267 
268   //
269   //  Send the Memory Type Registers page
270   //
271   for ( ; ; ) {
272     //
273     //  Send the page header
274     //
275     Status = HttpPageHeader ( SocketFD, pPort, L"Memory Type Range Registers" );
276     if ( EFI_ERROR ( Status )) {
277       break;
278     }
279 
280     //
281     //  Send the header
282     //
283     Status = HttpSendAnsiString ( SocketFD,
284                                   pPort,
285                                   "<h1>Memory Type Range Registers</h1>\r\n" );
286     if ( EFI_ERROR ( Status )) {
287       break;
288     }
289 
290     //
291     //  Determine if MTRRs are supported
292     //
293     if ( !IsMtrrSupported ( )) {
294       Status = HttpSendAnsiString ( SocketFD,
295                                     pPort,
296                                     "<p>Memory Type Range Registers are not supported!\r\n" );
297       if ( EFI_ERROR ( Status )) {
298         break;
299       }
300     }
301     else {
302       //
303       //  Get the capabilities
304       //
305       Capabilities = AsmReadMsr64 ( MTRR_LIB_IA32_MTRR_CAP );
306       DefType =  AsmReadMsr64 ( MTRR_LIB_IA32_MTRR_DEF_TYPE );
307 
308       //
309       //  Display the capabilities
310       //
311       Status = HttpSendAnsiString ( SocketFD,
312                                     pPort,
313                                     "<p>Capabilities: " );
314       if ( EFI_ERROR ( Status )) {
315         break;
316       }
317       Status = HttpSendHexValue ( SocketFD,
318                                   pPort,
319                                   Capabilities );
320       if ( EFI_ERROR ( Status )) {
321         break;
322       }
323       Status = HttpSendAnsiString ( SocketFD,
324                                     pPort,
325                                     "<br>\r\n" );
326       if ( EFI_ERROR ( Status )) {
327         break;
328       }
329 
330       //
331       //  Display the default type
332       //
333       Status = HttpSendAnsiString ( SocketFD,
334                                     pPort,
335                                     "Def Type: " );
336       if ( EFI_ERROR ( Status )) {
337         break;
338       }
339       Status = HttpSendHexValue ( SocketFD,
340                                   pPort,
341                                   DefType );
342       if ( EFI_ERROR ( Status )) {
343         break;
344       }
345       Status = HttpSendAnsiString ( SocketFD,
346                                     pPort,
347                                     ", MTRRs " );
348       if ( EFI_ERROR ( Status )) {
349         break;
350       }
351       Status = HttpSendAnsiString ( SocketFD,
352                                     pPort,
353                                     ( 0 != ( DefType & MTRR_LIB_CACHE_MTRR_ENABLED ))
354                                     ? "Enabled"
355                                     : "Disabled" );
356       if ( EFI_ERROR ( Status )) {
357         break;
358       }
359       Status = HttpSendAnsiString ( SocketFD,
360                                     pPort,
361                                     ", Fixed MTRRs " );
362       if ( EFI_ERROR ( Status )) {
363         break;
364       }
365       Status = HttpSendAnsiString ( SocketFD,
366                                     pPort,
367                                     ( 0 != ( DefType & MTRR_LIB_CACHE_FIXED_MTRR_ENABLED ))
368                                     ? "Enabled"
369                                     : "Disabled" );
370       if ( EFI_ERROR ( Status )) {
371         break;
372       }
373       Status = HttpSendAnsiString ( SocketFD,
374                                     pPort,
375                                     ", " );
376       if ( EFI_ERROR ( Status )) {
377         break;
378       }
379       Type = DefType & 0xff;
380       Status = HttpSendAnsiString ( SocketFD,
381                                     pPort,
382                                     ( DIM ( mMemoryType ) > Type )
383                                     ? mMemoryType [ Type ]
384                                     : "Reserved" );
385       if ( EFI_ERROR ( Status )) {
386         break;
387       }
388       Status = HttpSendAnsiString ( SocketFD,
389                                     pPort,
390                                     "</p>\r\n" );
391       if ( EFI_ERROR ( Status )) {
392         break;
393       }
394 
395       //
396       //  Determine if MTRRs are enabled
397       //
398       if ( 0 == ( DefType & MTRR_LIB_CACHE_MTRR_ENABLED )) {
399         Status = HttpSendAnsiString ( SocketFD,
400                                       pPort,
401                                       "<p>All memory is uncached!</p>\r\n" );
402         if ( EFI_ERROR ( Status )) {
403           break;
404         }
405       }
406       else {
407         //
408         //  Get the MTRRs
409         //
410         MtrrGetAllMtrrs ( &Mtrr );
411 
412         //
413         //  Determine if the fixed MTRRs are supported
414         //
415         if (( 0 != ( Capabilities & 0x100 ))
416           && ( 0 != ( DefType & MTRR_LIB_CACHE_FIXED_MTRR_ENABLED ))) {
417 
418           //
419           //  Beginning of table
420           //
421           Status = HttpSendAnsiString ( SocketFD,
422                                         pPort,
423                                         "<h2>Fixed MTRRs</h2>\r\n"
424                                         "<table>\r\n"
425                                         "  <tr><th>Index</th><th align=\"right\">Value</th><th align=\"right\">Start</th><th align=\"right\">End</th></tr>\r\n" );
426           if ( EFI_ERROR ( Status )) {
427             break;
428           }
429 
430           //
431           //  Display the fixed MTRRs
432           //
433           pMemStart = &mFixedAddresses[ 0 ];
434           for ( Count = 0; DIM ( Mtrr.Fixed.Mtrr ) > Count; Count++ ) {
435             //
436             //  Start the row
437             //
438             Status = HttpSendAnsiString ( SocketFD,
439                                           pPort,
440                                           "  <tr><td>" );
441             if ( EFI_ERROR ( Status )) {
442               break;
443             }
444 
445             //
446             //  Index
447             //
448             Status = HttpSendValue ( SocketFD,
449                                      pPort,
450                                      Count );
451             if ( EFI_ERROR ( Status )) {
452               break;
453             }
454 
455             //
456             //  Value
457             //
458             Status = HttpSendAnsiString ( SocketFD,
459                                           pPort,
460                                           "</td><td align=\"right\"><code>0x" );
461             if ( EFI_ERROR ( Status )) {
462               break;
463             }
464             Status = HttpSendHexValue ( SocketFD,
465                                         pPort,
466                                         Mtrr.Fixed.Mtrr[ Count ]);
467             if ( EFI_ERROR ( Status )) {
468               break;
469             }
470 
471             //
472             //  Start
473             //
474             Status = HttpSendAnsiString ( SocketFD,
475                                           pPort,
476                                           "</code></td><td align=\"right\"><code>0x" );
477             if ( EFI_ERROR ( Status )) {
478               break;
479             }
480             Status = HttpSendHexValue ( SocketFD,
481                                         pPort,
482                                         *pMemStart );
483             if ( EFI_ERROR ( Status )) {
484               break;
485             }
486             pMemStart += 8;
487 
488             //
489             //  Value
490             //
491             Status = HttpSendAnsiString ( SocketFD,
492                                           pPort,
493                                           "</code></td><td align=\"right\"><code>0x" );
494             if ( EFI_ERROR ( Status )) {
495               break;
496             }
497             Status = HttpSendHexValue ( SocketFD,
498                                         pPort,
499                                         *pMemStart - 1 );
500             if ( EFI_ERROR ( Status )) {
501               break;
502             }
503 
504             //
505             //  End of row
506             //
507             Status = HttpSendAnsiString ( SocketFD,
508                                           pPort,
509                                           "</code></td></tr>\r\n" );
510             if ( EFI_ERROR ( Status )) {
511               break;
512             }
513           }
514           if ( EFI_ERROR ( Status )) {
515             break;
516           }
517 
518           //
519           //  End of table
520           //
521           Status = HttpSendAnsiString ( SocketFD,
522                                         pPort,
523                                         "</table>\r\n" );
524           if ( EFI_ERROR ( Status )) {
525             break;
526           }
527 
528           //
529           //  Beginning of table
530           //
531           Status = HttpSendAnsiString ( SocketFD,
532                                         pPort,
533                                         "<table>\r\n"
534                                         "  <tr><th align=\"right\">Start</th><th align=\"right\">End</th><th align=\"left\">Type</th></tr>\r\n" );
535           if ( EFI_ERROR ( Status )) {
536             break;
537           }
538 
539           //
540           //  Decode the fixed MTRRs
541           //
542           PreviousType = Mtrr.Fixed.Mtrr[ 0 ] & 0xff;
543           pMemStart = &mFixedAddresses[ 0 ];
544           pMemEnd = pMemStart;
545           for ( Count = 0; DIM ( Mtrr.Fixed.Mtrr ) > Count; Count++ ) {
546             //
547             //  Get the memory types
548             //
549             Type = Mtrr.Fixed.Mtrr[ Count ];
550 
551             //
552             //  Walk the memory range
553             //
554             for ( Index = 0; 8 > Index; Index++ ) {
555               //
556               //  Determine if this is the same memory type
557               //
558               if ( PreviousType != ( Type & 0xff )) {
559                 //
560                 //  Display the row
561                 //
562                 Status = MtrrDisplayFixedRow ( SocketFD,
563                                                pPort,
564                                                *pMemStart,
565                                                *pMemEnd,
566                                                PreviousType );
567                 if ( EFI_ERROR ( Status )) {
568                   break;
569                 }
570 
571                 //
572                 //  Start the next range of addresses
573                 //
574                 pMemStart = pMemEnd;
575                 PreviousType = Type & 0xff;
576               }
577 
578               //
579               //  Set the next memory range and type
580               //
581               Type >>= 8;
582               pMemEnd += 1;
583             }
584             if ( EFI_ERROR ( Status )) {
585               break;
586             }
587           }
588           if ( EFI_ERROR ( Status )) {
589             break;
590           }
591 
592           //
593           //  Display the final row
594           //
595           Status = MtrrDisplayFixedRow ( SocketFD,
596                                          pPort,
597                                          *pMemStart,
598                                          *pMemEnd,
599                                          PreviousType );
600           if ( EFI_ERROR ( Status )) {
601             break;
602           }
603 
604           //
605           //  End of table
606           //
607           Status = HttpSendAnsiString ( SocketFD,
608                                         pPort,
609                                         "</table>\r\n" );
610           if ( EFI_ERROR ( Status )) {
611             break;
612           }
613         }
614 
615         //
616         //  Determine if the variable MTRRs are supported
617         //
618         MaxMtrrs = Capabilities & MTRR_LIB_IA32_MTRR_CAP_VCNT_MASK;
619         if ( 0 < MaxMtrrs ) {
620           //
621           //  Beginning of table
622           //
623           Status = HttpSendAnsiString ( SocketFD,
624                                         pPort,
625                                         "<h2>Variable MTRRs</h2>\r\n"
626                                         "<table>\r\n"
627                                         "  <tr><th>Index</th><th align=\"right\">Base</th><th align=\"right\">Mask</th><th align=\"right\">Start</th><th align=\"right\">End</th></tr>\r\n" );
628           if ( EFI_ERROR ( Status )) {
629             break;
630           }
631 
632           //
633           //  Display the variable MTRRs
634           //
635           for ( Count = 0; MaxMtrrs > Count; Count++ ) {
636             //
637             //  Start the row
638             //
639             Status = HttpSendAnsiString ( SocketFD,
640                                           pPort,
641                                           "  <tr><td>" );
642             if ( EFI_ERROR ( Status )) {
643               break;
644             }
645 
646             //
647             //  Index
648             //
649             Status = HttpSendValue ( SocketFD,
650                                      pPort,
651                                      Count );
652             if ( EFI_ERROR ( Status )) {
653               break;
654             }
655 
656             //
657             //  Base
658             //
659             Status = HttpSendAnsiString ( SocketFD,
660                                           pPort,
661                                           "</td><td align=\"right\"><code>0x" );
662             if ( EFI_ERROR ( Status )) {
663               break;
664             }
665             Status = HttpSendHexValue ( SocketFD,
666                                         pPort,
667                                         Mtrr.Variables.Mtrr[ Count ].Base );
668             if ( EFI_ERROR ( Status )) {
669               break;
670             }
671 
672             //
673             //  Mask
674             //
675             Status = HttpSendAnsiString ( SocketFD,
676                                           pPort,
677                                           "</td><td align=\"right\"><code>0x" );
678             if ( EFI_ERROR ( Status )) {
679               break;
680             }
681             Status = HttpSendHexValue ( SocketFD,
682                                         pPort,
683                                         Mtrr.Variables.Mtrr[ Count ].Mask );
684             if ( EFI_ERROR ( Status )) {
685               break;
686             }
687 
688             //
689             //  Determine if the entry is valid
690             //
691             bValid = ( Mtrr.Variables.Mtrr[ Count ].Mask & VARIABLE_MTRR_VALID ) ? TRUE : FALSE;
692 
693             //
694             //  Start
695             //
696             Status = HttpSendAnsiString ( SocketFD,
697                                           pPort,
698                                           "</code></td><td align=\"right\"><code>" );
699             if ( EFI_ERROR ( Status )) {
700               break;
701             }
702             Addr = Mtrr.Variables.Mtrr[ Count ].Base & 0xfffffffffffff000ULL;
703             if ( bValid ) {
704               Status = HttpSendAnsiString ( SocketFD,
705                                             pPort,
706                                             "0x" );
707               if ( EFI_ERROR ( Status )) {
708                 break;
709               }
710               Status = HttpSendHexValue ( SocketFD,
711                                           pPort,
712                                           Addr );
713             }
714             else {
715               Status = HttpSendAnsiString ( SocketFD,
716                                             pPort,
717                                             "Invalid" );
718             }
719             if ( EFI_ERROR ( Status )) {
720               break;
721             }
722 
723             //
724             //  End
725             //
726             Status = HttpSendAnsiString ( SocketFD,
727                                           pPort,
728                                           "</code></td><td align=\"right\"><code>" );
729             if ( EFI_ERROR ( Status )) {
730               break;
731             }
732             if ( bValid ) {
733               //
734               //  Determine the end address
735               //
736               Mask = Mtrr.Variables.Mtrr[ Count ].Mask;
737               Value = Mask;
738               ShiftCount = 0;
739               while ( 0 < Value ) {
740                 Value <<= 1;
741                 ShiftCount += 1;
742               }
743               Value = 1;
744               Value <<= 64 - ShiftCount;
745               Value -= 1;
746               Value = ~Value;
747               Value |= Mask;
748               Value &= ~VARIABLE_MTRR_VALID;
749               Value = ~Value;
750 
751               Status = HttpSendAnsiString ( SocketFD,
752                                             pPort,
753                                             "0x" );
754               if ( EFI_ERROR ( Status )) {
755                 break;
756               }
757               Status = HttpSendHexValue ( SocketFD,
758                                           pPort,
759                                           Addr + Value );
760             }
761             if ( EFI_ERROR ( Status )) {
762               break;
763             }
764 
765             //
766             //  Type
767             //
768             Status = HttpSendAnsiString ( SocketFD,
769                                           pPort,
770                                           "</code></td><td>" );
771             if ( EFI_ERROR ( Status )) {
772               break;
773             }
774             if ( bValid ) {
775               Type = Mtrr.Variables.Mtrr[ Count ].Base & 0xFF;
776               Status = HttpSendAnsiString ( SocketFD,
777                                             pPort,
778                                             ( DIM ( mMemoryType ) > Type )
779                                             ? mMemoryType [ Type ]
780                                             : "Reserved" );
781             }
782             if ( EFI_ERROR ( Status )) {
783               break;
784             }
785 
786             //
787             //  End of row
788             //
789             Status = HttpSendAnsiString ( SocketFD,
790                                           pPort,
791                                           "</td></tr>\r\n" );
792             if ( EFI_ERROR ( Status )) {
793               break;
794             }
795           }
796           if ( EFI_ERROR ( Status )) {
797             break;
798           }
799 
800           //
801           //  End of table
802           //
803           Status = HttpSendAnsiString ( SocketFD,
804                                         pPort,
805                                         "</table>\r\n" );
806           if ( EFI_ERROR ( Status )) {
807             break;
808           }
809         }
810       }
811     }
812 
813     //
814     //  Send the page trailer
815     //
816     Status = HttpPageTrailer ( SocketFD, pPort, pbDone );
817     break;
818   }
819 
820   //
821   //  Return the operation status
822   //
823   DBG_EXIT_STATUS ( Status );
824   return Status;
825 }
826