1 /**
2   @file
3   Display the system table
4 
5   Copyright (c) 2011-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 
18 
19 /**
20   Display the EFI Table Header
21 
22   @param [in] SocketFD      The socket's file descriptor to add to the list.
23   @param [in] pPort         The WSDT_PORT structure address
24   @param [in] pHeader       Address of the EFI_TABLE_HEADER structure
25 
26   @retval EFI_SUCCESS       The request was successfully processed
27 
28 **/
29 EFI_STATUS
EfiTableHeader(IN int SocketFD,IN WSDT_PORT * pPort,IN EFI_TABLE_HEADER * pHeader)30 EfiTableHeader (
31   IN int SocketFD,
32   IN WSDT_PORT * pPort,
33   IN EFI_TABLE_HEADER * pHeader
34   )
35 {
36   EFI_STATUS Status;
37 
38   DBG_ENTER ( );
39 
40   //
41   //  Send the handles page
42   //
43   for ( ; ; ) {
44     ///
45     /// A 64-bit signature that identifies the type of table that follows.
46     /// Unique signatures have been generated for the EFI System Table,
47     /// the EFI Boot Services Table, and the EFI Runtime Services Table.
48     ///
49     Status = RowHexValue ( SocketFD,
50                            pPort,
51                            "Hdr.Signature",
52                            pHeader->Signature,
53                            NULL );
54     if ( EFI_ERROR ( Status )) {
55       break;
56     }
57 
58     ///
59     /// The revision of the EFI Specification to which this table
60     /// conforms. The upper 16 bits of this field contain the major
61     /// revision value, and the lower 16 bits contain the minor revision
62     /// value. The minor revision values are limited to the range of 00..99.
63     ///
64     Status = RowRevision ( SocketFD,
65                            pPort,
66                            "Hdr.Revision",
67                            pHeader->Revision );
68     if ( EFI_ERROR ( Status )) {
69       break;
70     }
71 
72     ///
73     /// The size, in bytes, of the entire table including the EFI_TABLE_HEADER.
74     ///
75     Status = RowDecimalValue ( SocketFD,
76                                pPort,
77                                "Hdr.HeaderSize",
78                                pHeader->HeaderSize );
79     if ( EFI_ERROR ( Status )) {
80       break;
81     }
82 
83     ///
84     /// The 32-bit CRC for the entire table. This value is computed by
85     /// setting this field to 0, and computing the 32-bit CRC for HeaderSize bytes.
86     ///
87     Status = RowHexValue ( SocketFD,
88                            pPort,
89                            "Hdr.CRC",
90                            pHeader->CRC32,
91                            NULL );
92     if ( EFI_ERROR ( Status )) {
93       break;
94     }
95 
96     ///
97     /// Reserved field that must be set to 0.
98     ///
99     Status = RowHexValue ( SocketFD,
100                            pPort,
101                            "Hdr.Reserved",
102                            pHeader->Reserved,
103                            NULL );
104     break;
105   }
106 
107   //
108   //  Return the operation status
109   //
110   DBG_EXIT_STATUS ( Status );
111   return Status;
112 }
113 
114 
115 /**
116   Display a row containing a decimal value
117 
118   @param [in] SocketFD      The socket's file descriptor to add to the list.
119   @param [in] pPort         The WSDT_PORT structure address
120   @param [in] pName         Address of a zero terminated name string
121   @param [in] Value         The value to display
122 
123   @retval EFI_SUCCESS       The request was successfully processed
124 
125 **/
126 EFI_STATUS
RowDecimalValue(IN int SocketFD,IN WSDT_PORT * pPort,IN CONST CHAR8 * pName,IN UINT64 Value)127 RowDecimalValue (
128   IN int SocketFD,
129   IN WSDT_PORT * pPort,
130   IN CONST CHAR8 * pName,
131   IN UINT64 Value
132   )
133 {
134   EFI_STATUS Status;
135 
136   DBG_ENTER ( );
137 
138   //
139   //  Use for/break instead of goto
140   //
141   for ( ; ; ) {
142     Status = HttpSendAnsiString ( SocketFD,
143                                   pPort,
144                                   "<tr><td>" );
145     if ( EFI_ERROR ( Status )) {
146       break;
147     }
148     Status = HttpSendAnsiString ( SocketFD,
149                                   pPort,
150                                   pName );
151     if ( EFI_ERROR ( Status )) {
152       break;
153     }
154     Status = HttpSendAnsiString ( SocketFD,
155                                   pPort,
156                                   "</td><td><code>" );
157     if ( EFI_ERROR ( Status )) {
158       break;
159     }
160     Status = HttpSendValue ( SocketFD,
161                              pPort,
162                              Value );
163     if ( EFI_ERROR ( Status )) {
164       break;
165     }
166     Status = HttpSendAnsiString ( SocketFD,
167                                   pPort,
168                                   "</code></td></tr>\r\n" );
169     break;
170   }
171 
172   //
173   //  Return the operation status
174   //
175   DBG_EXIT_STATUS ( Status );
176   return Status;
177 }
178 
179 
180 /**
181   Display a row containing a hex value
182 
183   @param [in] SocketFD      The socket's file descriptor to add to the list.
184   @param [in] pPort         The WSDT_PORT structure address
185   @param [in] pName         Address of a zero terminated name string
186   @param [in] Value         The value to display
187   @param [in] pWebPage      Address of a zero terminated web page name
188 
189   @retval EFI_SUCCESS       The request was successfully processed
190 
191 **/
192 EFI_STATUS
RowHexValue(IN int SocketFD,IN WSDT_PORT * pPort,IN CONST CHAR8 * pName,IN UINT64 Value,IN CONST CHAR16 * pWebPage)193 RowHexValue (
194   IN int SocketFD,
195   IN WSDT_PORT * pPort,
196   IN CONST CHAR8 * pName,
197   IN UINT64 Value,
198   IN CONST CHAR16 * pWebPage
199   )
200 {
201   EFI_STATUS Status;
202 
203   DBG_ENTER ( );
204 
205   //
206   //  Use for/break instead of goto
207   //
208   for ( ; ; ) {
209     Status = HttpSendAnsiString ( SocketFD,
210                                   pPort,
211                                   "<tr><td>" );
212     if ( EFI_ERROR ( Status )) {
213       break;
214     }
215     Status = HttpSendAnsiString ( SocketFD,
216                                   pPort,
217                                   pName );
218     if ( EFI_ERROR ( Status )) {
219       break;
220     }
221     Status = HttpSendAnsiString ( SocketFD,
222                                   pPort,
223                                   "</td><td><code>0x" );
224     if ( EFI_ERROR ( Status )) {
225       break;
226     }
227     if ( NULL != pWebPage ) {
228       Status = HttpSendAnsiString ( SocketFD,
229                                     pPort,
230                                     "<a target=\"_blank\" href=\"" );
231       if ( EFI_ERROR ( Status )) {
232         break;
233       }
234       Status = HttpSendUnicodeString ( SocketFD,
235                                        pPort,
236                                        pWebPage );
237       if ( EFI_ERROR ( Status )) {
238         break;
239       }
240       Status = HttpSendAnsiString ( SocketFD,
241                                     pPort,
242                                     "\">" );
243       if ( EFI_ERROR ( Status )) {
244         break;
245       }
246     }
247     Status = HttpSendHexValue ( SocketFD,
248                                 pPort,
249                                 Value );
250     if ( EFI_ERROR ( Status )) {
251       break;
252     }
253     if ( NULL != pWebPage ) {
254       Status = HttpSendAnsiString ( SocketFD,
255                                     pPort,
256                                     "</a>" );
257       if ( EFI_ERROR ( Status )) {
258         break;
259       }
260     }
261     Status = HttpSendAnsiString ( SocketFD,
262                                   pPort,
263                                   "</code></td></tr>\r\n" );
264     break;
265   }
266 
267   //
268   //  Return the operation status
269   //
270   DBG_EXIT_STATUS ( Status );
271   return Status;
272 }
273 
274 
275 /**
276   Display a row containing a pointer
277 
278   @param [in] SocketFD      The socket's file descriptor to add to the list.
279   @param [in] pPort         The WSDT_PORT structure address
280   @param [in] pName         Address of a zero terminated name string
281   @param [in] pAddress      The address to display
282   @param [in] pWebPage      Address of a zero terminated web page name
283 
284   @retval EFI_SUCCESS       The request was successfully processed
285 
286 **/
287 EFI_STATUS
RowPointer(IN int SocketFD,IN WSDT_PORT * pPort,IN CONST CHAR8 * pName,IN CONST VOID * pAddress,IN CONST CHAR16 * pWebPage)288 RowPointer (
289   IN int SocketFD,
290   IN WSDT_PORT * pPort,
291   IN CONST CHAR8 * pName,
292   IN CONST VOID * pAddress,
293   IN CONST CHAR16 * pWebPage
294   )
295 {
296   EFI_STATUS Status;
297 
298   DBG_ENTER ( );
299 
300   //
301   //  Use for/break instead of goto
302   //
303   for ( ; ; ) {
304     Status = HttpSendAnsiString ( SocketFD,
305                                   pPort,
306                                   "<tr><td>" );
307     if ( EFI_ERROR ( Status )) {
308       break;
309     }
310     Status = HttpSendAnsiString ( SocketFD,
311                                   pPort,
312                                   pName );
313     if ( EFI_ERROR ( Status )) {
314       break;
315     }
316     Status = HttpSendAnsiString ( SocketFD,
317                                   pPort,
318                                   "</td><td><code>" );
319     if ( EFI_ERROR ( Status )) {
320       break;
321     }
322     if ( NULL != pWebPage ) {
323       Status = HttpSendAnsiString ( SocketFD,
324                                     pPort,
325                                     "<a target=\"_blank\" href=\"" );
326       if ( EFI_ERROR ( Status )) {
327         break;
328       }
329       Status = HttpSendUnicodeString ( SocketFD,
330                                        pPort,
331                                        pWebPage );
332       if ( EFI_ERROR ( Status )) {
333         break;
334       }
335       Status = HttpSendAnsiString ( SocketFD,
336                                     pPort,
337                                     "\">" );
338       if ( EFI_ERROR ( Status )) {
339         break;
340       }
341     }
342     Status = HttpSendAnsiString ( SocketFD,
343                                   pPort,
344                                   "0x" );
345     if ( EFI_ERROR ( Status )) {
346       break;
347     }
348     Status = HttpSendHexBits ( SocketFD,
349                                pPort,
350                                sizeof ( pAddress ) * 8,
351                                (UINT64)(UINTN)pAddress );
352     if ( EFI_ERROR ( Status )) {
353       break;
354     }
355     if ( NULL != pWebPage ) {
356       Status = HttpSendAnsiString ( SocketFD,
357                                     pPort,
358                                     "</a>" );
359       if ( EFI_ERROR ( Status )) {
360         break;
361       }
362     }
363     Status = HttpSendAnsiString ( SocketFD,
364                                   pPort,
365                                   "</code></td></tr>\r\n" );
366     break;
367   }
368 
369   //
370   //  Return the operation status
371   //
372   DBG_EXIT_STATUS ( Status );
373   return Status;
374 }
375 
376 
377 /**
378   Display a row containing a revision
379 
380   @param [in] SocketFD      The socket's file descriptor to add to the list.
381   @param [in] pPort         The WSDT_PORT structure address
382   @param [in] pName         Address of a zero terminated name string
383   @param [in] Revision      The revision to display
384 
385   @retval EFI_SUCCESS       The request was successfully processed
386 
387 **/
388 EFI_STATUS
RowRevision(IN int SocketFD,IN WSDT_PORT * pPort,IN CONST CHAR8 * pName,IN UINT32 Revision)389 RowRevision (
390   IN int SocketFD,
391   IN WSDT_PORT * pPort,
392   IN CONST CHAR8 * pName,
393   IN UINT32 Revision
394   )
395 {
396   EFI_STATUS Status;
397 
398   DBG_ENTER ( );
399 
400   //
401   //  Use for/break instead of goto
402   //
403   for ( ; ; ) {
404     Status = HttpSendAnsiString ( SocketFD,
405                                   pPort,
406                                   "<tr><td>" );
407     if ( EFI_ERROR ( Status )) {
408       break;
409     }
410     Status = HttpSendAnsiString ( SocketFD,
411                                   pPort,
412                                   pName );
413     if ( EFI_ERROR ( Status )) {
414       break;
415     }
416     Status = HttpSendAnsiString ( SocketFD,
417                                   pPort,
418                                   "</td><td><code>" );
419     if ( EFI_ERROR ( Status )) {
420       break;
421     }
422     Status = HttpSendValue ( SocketFD,
423                              pPort,
424                              Revision >> 16 );
425     if ( EFI_ERROR ( Status )) {
426       break;
427     }
428     Status = HttpSendByte ( SocketFD,
429                             pPort,
430                             '.' );
431     if ( EFI_ERROR ( Status )) {
432       break;
433     }
434     Status = HttpSendValue ( SocketFD,
435                              pPort,
436                              Revision & 0xFFFF );
437     if ( EFI_ERROR ( Status )) {
438       break;
439     }
440     Status = HttpSendAnsiString ( SocketFD,
441                                   pPort,
442                                   "</code></td></tr>\r\n" );
443     break;
444   }
445 
446   //
447   //  Return the operation status
448   //
449   DBG_EXIT_STATUS ( Status );
450   return Status;
451 }
452 
453 
454 /**
455   Display a row containing a unicode string
456 
457   @param [in] SocketFD      The socket's file descriptor to add to the list.
458   @param [in] pPort         The WSDT_PORT structure address
459   @param [in] pName         Address of a zero terminated name string
460   @param [in] pString       Address of a zero terminated unicode string
461 
462   @retval EFI_SUCCESS       The request was successfully processed
463 
464 **/
465 EFI_STATUS
RowUnicodeString(IN int SocketFD,IN WSDT_PORT * pPort,IN CONST CHAR8 * pName,IN CONST CHAR16 * pString)466 RowUnicodeString (
467   IN int SocketFD,
468   IN WSDT_PORT * pPort,
469   IN CONST CHAR8 * pName,
470   IN CONST CHAR16 * pString
471   )
472 {
473   EFI_STATUS Status;
474 
475   DBG_ENTER ( );
476 
477   //
478   //  Use for/break instead of goto
479   //
480   for ( ; ; ) {
481     Status = HttpSendAnsiString ( SocketFD,
482                                   pPort,
483                                   "<tr><td>" );
484     if ( EFI_ERROR ( Status )) {
485       break;
486     }
487     Status = HttpSendAnsiString ( SocketFD,
488                                   pPort,
489                                   pName );
490     if ( EFI_ERROR ( Status )) {
491       break;
492     }
493     Status = HttpSendAnsiString ( SocketFD,
494                                   pPort,
495                                   "</td><td>" );
496     if ( EFI_ERROR ( Status )) {
497       break;
498     }
499     Status = HttpSendUnicodeString ( SocketFD,
500                                      pPort,
501                                      pString );
502     if ( EFI_ERROR ( Status )) {
503       break;
504     }
505     Status = HttpSendAnsiString ( SocketFD,
506                                   pPort,
507                                   "</td></tr>\r\n" );
508     break;
509   }
510 
511   //
512   //  Return the operation status
513   //
514   DBG_EXIT_STATUS ( Status );
515   return Status;
516 }
517 
518 
519 /**
520   Start the table page
521 
522   @param [in] SocketFD      The socket's file descriptor to add to the list.
523   @param [in] pPort         The WSDT_PORT structure address
524   @param [in] pName         Address of a zero terminated name string
525   @param [in] pTable        Address of the table
526 
527   @retval EFI_SUCCESS       The request was successfully processed
528 
529 **/
530 EFI_STATUS
TableHeader(IN int SocketFD,IN WSDT_PORT * pPort,IN CONST CHAR16 * pName,IN CONST VOID * pTable)531 TableHeader (
532   IN int SocketFD,
533   IN WSDT_PORT * pPort,
534   IN CONST CHAR16 * pName,
535   IN CONST VOID * pTable
536   )
537 {
538   EFI_STATUS Status;
539 
540   DBG_ENTER ( );
541 
542   //
543   //  Use for/break instead of goto
544   //
545   for ( ; ; ) {
546     //
547     //  Send the page header
548     //
549     Status = HttpPageHeader ( SocketFD, pPort, pName );
550     if ( EFI_ERROR ( Status )) {
551       break;
552     }
553 
554     //
555     //  Build the table header
556     //
557     Status = HttpSendAnsiString ( SocketFD,
558                                   pPort,
559                                   "<h1>" );
560     if ( EFI_ERROR ( Status )) {
561       break;
562     }
563     Status = HttpSendUnicodeString ( SocketFD,
564                                      pPort,
565                                      pName );
566     if ( EFI_ERROR ( Status )) {
567       break;
568     }
569     if ( NULL != pTable ) {
570       Status = HttpSendAnsiString ( SocketFD,
571                                     pPort,
572                                     ": 0x" );
573       if ( EFI_ERROR ( Status )) {
574         break;
575       }
576       Status = HttpSendHexBits ( SocketFD,
577                                  pPort,
578                                  sizeof ( pTable ) *  8,
579                                  (UINT64)(UINTN)pTable );
580       if ( EFI_ERROR ( Status )) {
581         break;
582       }
583     }
584     Status = HttpSendAnsiString ( SocketFD,
585                                   pPort,
586                                   "</h1>\r\n"
587                                   "<table border=\"1\">\r\n"
588                                   "  <tr bgcolor=\"c0c0ff\"><th>Field Name</th><th>Value</th></tr>\r\n" );
589     break;
590   }
591 
592   //
593   //  Return the operation status
594   //
595   DBG_EXIT_STATUS ( Status );
596   return Status;
597 }
598 
599 
600 /**
601   End the table page
602 
603   @param [in] SocketFD      The socket's file descriptor to add to the list.
604   @param [in] pPort         The WSDT_PORT structure address
605   @param [out] pbDone       Address to receive the request completion status
606 
607   @retval EFI_SUCCESS       The request was successfully processed
608 
609 **/
610 EFI_STATUS
TableTrailer(IN int SocketFD,IN WSDT_PORT * pPort,OUT BOOLEAN * pbDone)611 TableTrailer (
612   IN int SocketFD,
613   IN WSDT_PORT * pPort,
614   OUT BOOLEAN *pbDone
615   )
616 {
617   EFI_STATUS Status;
618 
619   DBG_ENTER ( );
620 
621   //
622   //  Use for/break instead of goto
623   //
624   for ( ; ; ) {
625     //
626     //  Build the table trailer
627     //
628     Status = HttpSendAnsiString ( SocketFD,
629                                   pPort,
630                                   "</table>\r\n" );
631     if ( EFI_ERROR ( Status )) {
632       break;
633     }
634 
635     //
636     //  Send the page trailer
637     //
638     Status = HttpPageTrailer ( SocketFD, pPort, pbDone );
639     break;
640   }
641 
642   //
643   //  Return the operation status
644   //
645   DBG_EXIT_STATUS ( Status );
646   return Status;
647 }
648 
649 
650 /**
651   Respond with the system table
652 
653   @param [in] SocketFD      The socket's file descriptor to add to the list.
654   @param [in] pPort         The WSDT_PORT structure address
655   @param [out] pbDone       Address to receive the request completion status
656 
657   @retval EFI_SUCCESS       The request was successfully processed
658 
659 **/
660 EFI_STATUS
SystemTablePage(IN int SocketFD,IN WSDT_PORT * pPort,OUT BOOLEAN * pbDone)661 SystemTablePage (
662   IN int SocketFD,
663   IN WSDT_PORT * pPort,
664   OUT BOOLEAN * pbDone
665   )
666 {
667   EFI_STATUS Status;
668 
669   DBG_ENTER ( );
670 
671   //
672   //  Send the system table page
673   //
674   for ( ; ; ) {
675     //
676     //  Send the page and table header
677     //
678     Status = TableHeader ( SocketFD, pPort, L"System Table", gST );
679     if ( EFI_ERROR ( Status )) {
680       break;
681     }
682 
683     ///
684     /// The table header for the EFI System Table.
685     ///
686     Status = EfiTableHeader ( SocketFD,
687                               pPort,
688                               &gST->Hdr );
689     if ( EFI_ERROR ( Status )) {
690       break;
691     }
692 
693     ///
694     /// A pointer to a null terminated string that identifies the vendor
695     /// that produces the system firmware for the platform.
696     ///
697     Status = RowUnicodeString ( SocketFD,
698                                 pPort,
699                                 "FirmwareVendor",
700                                 gST->FirmwareVendor );
701     if ( EFI_ERROR ( Status )) {
702       break;
703     }
704 
705     ///
706     /// A firmware vendor specific value that identifies the revision
707     /// of the system firmware for the platform.
708     ///
709     Status = RowRevision ( SocketFD,
710                            pPort,
711                            "FirmwareRevision",
712                            gST->FirmwareRevision );
713     if ( EFI_ERROR ( Status )) {
714       break;
715     }
716 
717     ///
718     /// The handle for the active console input device. This handle must support
719     /// EFI_SIMPLE_TEXT_INPUT_PROTOCOL and EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
720     ///
721     Status = RowPointer ( SocketFD,
722                           pPort,
723                           "ConsoleInHandle",
724                           (VOID *)gST->ConsoleInHandle,
725                           NULL );
726     if ( EFI_ERROR ( Status )) {
727       break;
728     }
729 
730     ///
731     /// A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL interface that is
732     /// associated with ConsoleInHandle.
733     ///
734     Status = RowPointer ( SocketFD,
735                           pPort,
736                           "ConIn",
737                           (VOID *)gST->ConIn,
738                           NULL );
739     if ( EFI_ERROR ( Status )) {
740       break;
741     }
742 
743     ///
744     /// The handle for the active console output device.
745     ///
746     Status = RowPointer ( SocketFD,
747                           pPort,
748                           "ConsoleOutHandle",
749                           (VOID *)gST->ConsoleOutHandle,
750                           NULL );
751     if ( EFI_ERROR ( Status )) {
752       break;
753     }
754 
755     ///
756     /// A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface
757     /// that is associated with ConsoleOutHandle.
758     ///
759     Status = RowPointer ( SocketFD,
760                           pPort,
761                           "ConOut",
762                           (VOID *)gST->ConOut,
763                           NULL );
764     if ( EFI_ERROR ( Status )) {
765       break;
766     }
767 
768     ///
769     /// The handle for the active standard error console device.
770     /// This handle must support the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.
771     ///
772     Status = RowPointer ( SocketFD,
773                           pPort,
774                           "StandardErrorHandle",
775                           (VOID *)gST->StandardErrorHandle,
776                           NULL );
777     if ( EFI_ERROR ( Status )) {
778       break;
779     }
780 
781     ///
782     /// A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface
783     /// that is associated with StandardErrorHandle.
784     ///
785     Status = RowPointer ( SocketFD,
786                           pPort,
787                           "StdErr",
788                           (VOID *)gST->StdErr,
789                           NULL );
790     if ( EFI_ERROR ( Status )) {
791       break;
792     }
793 
794     ///
795     /// A pointer to the EFI Runtime Services Table.
796     ///
797     Status = RowPointer ( SocketFD,
798                           pPort,
799                           "RuntimeServices",
800                           (VOID *)gST->RuntimeServices,
801                           PAGE_RUNTIME_SERVICES_TABLE );
802 
803     ///
804     /// A pointer to the EFI Boot Services Table.
805     ///
806     Status = RowPointer ( SocketFD,
807                           pPort,
808                           "BootServices",
809                           (VOID *)gST->BootServices,
810                           PAGE_BOOT_SERVICES_TABLE );
811     if ( EFI_ERROR ( Status )) {
812       break;
813     }
814 
815     ///
816     /// The number of system configuration tables in the buffer ConfigurationTable.
817     ///
818     Status = RowDecimalValue ( SocketFD,
819                                pPort,
820                                "NumberOfTableEntries",
821                                gST->NumberOfTableEntries );
822     if ( EFI_ERROR ( Status )) {
823       break;
824     }
825 
826     ///
827     /// A pointer to the system configuration tables.
828     /// The number of entries in the table is NumberOfTableEntries.
829     ///
830     Status = RowPointer ( SocketFD,
831                           pPort,
832                           "ConfigurationTable",
833                           (VOID *)gST->ConfigurationTable,
834                           PAGE_CONFIGURATION_TABLE );
835     if ( EFI_ERROR ( Status )) {
836       break;
837     }
838 
839     //
840     //  Build the table trailer
841     //
842     Status = TableTrailer ( SocketFD,
843                             pPort,
844                             pbDone );
845     break;
846   }
847 
848   //
849   //  Return the operation status
850   //
851   DBG_EXIT_STATUS ( Status );
852   return Status;
853 }
854