Home | History | Annotate | Download | only in WebServer
      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
     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
    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