1 /**
2   @file
3   Display the configuration 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 #include <Guid/Acpi.h>
18 #include <Guid/DebugImageInfoTable.h>
19 #include <Guid/DxeServices.h>
20 #include <Guid/HobList.h>
21 #include <Guid/MemoryTypeInformation.h>
22 #include <Guid/LoadModuleAtFixedAddress.h>
23 
24 
25 typedef struct {
26   CHAR16 * GuidName;
27   EFI_GUID * pGuid;
28   CHAR16 * pWebPage;
29 } GUID_NAME;
30 
31 CONST GUID_NAME mGuidName[] = {
32   { L"gEfiAcpi10TableGuid", &gEfiAcpi10TableGuid, PAGE_ACPI_RSDP_10B },
33   { L"gEfiAcpiTableGuid", &gEfiAcpiTableGuid, PAGE_ACPI_RSDP_30 },
34   { L"gEfiDebugImageInfoTableGuid", &gEfiDebugImageInfoTableGuid, NULL },
35   { L"gEfiDxeServicesTableGuid", &gEfiDxeServicesTableGuid, PAGE_DXE_SERVICES_TABLE },
36   { L"gEfiHobListGuid", &gEfiHobListGuid, NULL },
37   { L"gEfiMemoryTypeInformationGuid", &gEfiMemoryTypeInformationGuid, NULL },
38   { L"gLoadFixedAddressConfigurationTableGuid", &gLoadFixedAddressConfigurationTableGuid, NULL }
39 };
40 
41 /**
42   Display a row containing a GUID value
43 
44   @param [in] SocketFD      The socket's file descriptor to add to the list.
45   @param [in] pPort         The WSDT_PORT structure address
46   @param [in] pName         Address of a zero terminated name string
47   @param [in] pGuid         Address of the GUID to display
48 
49   @retval EFI_SUCCESS       The request was successfully processed
50 
51 **/
52 EFI_STATUS
RowGuid(IN int SocketFD,IN WSDT_PORT * pPort,IN CONST CHAR8 * pName,IN CONST EFI_GUID * pGuid)53 RowGuid (
54   IN int SocketFD,
55   IN WSDT_PORT * pPort,
56   IN CONST CHAR8 * pName,
57   IN CONST EFI_GUID * pGuid
58   )
59 {
60   CONST GUID_NAME * pGuidName;
61   CONST GUID_NAME * pGuidNameEnd;
62   EFI_STATUS Status;
63   UINTN Value;
64 
65   DBG_ENTER ( );
66 
67   //
68   //  Use for/break instead of goto
69   //
70   for ( ; ; ) {
71     Status = HttpSendAnsiString ( SocketFD,
72                                   pPort,
73                                   "<tr><td>" );
74     if ( EFI_ERROR ( Status )) {
75       break;
76     }
77     Status = HttpSendAnsiString ( SocketFD,
78                                   pPort,
79                                   pName );
80     if ( EFI_ERROR ( Status )) {
81       break;
82     }
83     Status = HttpSendAnsiString ( SocketFD,
84                                   pPort,
85                                   "</td><td><code>" );
86     if ( EFI_ERROR ( Status )) {
87       break;
88     }
89 
90     //
91     //  Determine if this is a known GUID
92     //
93     pGuidName = &mGuidName[0];
94     pGuidNameEnd = &pGuidName[ sizeof ( mGuidName ) / sizeof ( mGuidName[0])];
95     while ( pGuidNameEnd > pGuidName ) {
96       if ( CompareGuid ( pGuidName->pGuid, pGuid )) {
97         //
98         //  Display the web link if available
99         //
100         if ( NULL != pGuidName->pWebPage ) {
101           Status = HttpSendAnsiString ( SocketFD,
102                                         pPort,
103                                         "<a target=\"_blank\" href=\"" );
104           if ( EFI_ERROR ( Status )) {
105             break;
106           }
107           Status = HttpSendUnicodeString ( SocketFD,
108                                            pPort,
109                                            pGuidName->pWebPage );
110           if ( EFI_ERROR ( Status )) {
111             break;
112           }
113           Status = HttpSendAnsiString ( SocketFD,
114                                         pPort,
115                                         "\">" );
116           if ( EFI_ERROR ( Status )) {
117             break;
118           }
119         }
120 
121         //
122         //  Display the GUID name
123         //
124         Status = HttpSendUnicodeString ( SocketFD,
125                                          pPort,
126                                          pGuidName->GuidName );
127 
128         //
129         //  Complete the web link if available
130         //
131         if ( NULL != pGuidName->pWebPage ) {
132           if ( EFI_ERROR ( Status )) {
133             break;
134           }
135           Status = HttpSendAnsiString ( SocketFD,
136                                         pPort,
137                                         "</a>" );
138         }
139         break;
140       }
141 
142       //
143       //  Set the next GUID name
144       //
145       pGuidName += 1;
146     }
147     if ( EFI_ERROR ( Status )) {
148       break;
149     }
150 
151     //
152     //  Only if the entry is not known, display the GUID and type
153     //
154     if ( pGuidNameEnd <= pGuidName ) {
155       //
156       //  Display the GUID
157       //
158       Status = HttpSendGuid ( SocketFD,
159                               pPort,
160                               pGuid );
161       if ( EFI_ERROR ( Status )) {
162         break;
163       }
164 
165       //
166       //  Display the GUID type
167       //
168       Status = HttpSendAnsiString ( SocketFD,
169                                     pPort,
170                                     "<br/><a target=\"_blank\" href=\"http://www.ietf.org/rfc/rfc4122.txt\">Guid Type</a>: " );
171       if ( EFI_ERROR ( Status )) {
172         break;
173       }
174       Value = pGuid->Data4[1];
175       Value >>= 5;
176       if ( 3 >= Value ) {
177         //
178         //  Network type
179         //
180         Status = HttpSendAnsiString ( SocketFD,
181                                       pPort,
182                                       "Network " );
183       }
184       else if ( 5 >= Value ) {
185         //
186         //  Standard type
187         //
188         Status = HttpSendAnsiString ( SocketFD,
189                                       pPort,
190                                       "Standard " );
191         if ( EFI_ERROR ( Status )) {
192           break;
193         }
194 
195         //
196         //  Decode the standard type using RFC 4122
197         //
198         Value = pGuid->Data3;
199         Value >>= 12;
200         switch ( Value ) {
201         default:
202           //
203           //  Display the MAC address
204           //
205           Status = HttpSendAnsiString ( SocketFD,
206                                         pPort,
207                                         "Version " );
208           if ( EFI_ERROR ( Status )) {
209             break;
210           }
211           Status = HttpSendValue ( SocketFD,
212                                    pPort,
213                                    pGuid->Data3 >> 12 );
214           break;
215 
216         case 1:
217           Status = HttpSendAnsiString ( SocketFD,
218                                         pPort,
219                                         "MAC address" );
220           break;
221 
222         case 2:
223           Status = HttpSendAnsiString ( SocketFD,
224                                         pPort,
225                                         "DCE Security" );
226           break;
227 
228         case 3:
229           Status = HttpSendAnsiString ( SocketFD,
230                                         pPort,
231                                         "MD5 hash" );
232           break;
233 
234         case 4:
235           Status = HttpSendAnsiString ( SocketFD,
236                                         pPort,
237                                         "Random" );
238           break;
239 
240         case 5:
241           Status = HttpSendAnsiString ( SocketFD,
242                                         pPort,
243                                         "SHA-1 hash" );
244           break;
245         }
246       }
247       else if ( 6 == Value ) {
248         //
249         //  Microsoft's Component Object Model (COM) type
250         //
251         Status = HttpSendAnsiString ( SocketFD,
252                                       pPort,
253                                       "Microsoft COM" );
254       }
255       else {
256         //
257         //  Reserved type
258         //
259         Status = HttpSendAnsiString ( SocketFD,
260                                       pPort,
261                                       "Reserved" );
262       }
263     }
264 
265     //
266     //  Done with this entry
267     //
268     Status = HttpSendAnsiString ( SocketFD,
269                                   pPort,
270                                   "</code></td></tr>\r\n" );
271     break;
272   }
273 
274   //
275   //  Return the operation status
276   //
277   DBG_EXIT_STATUS ( Status );
278   return Status;
279 }
280 
281 
282 /**
283   Respond with the configuration tables
284 
285   @param [in] SocketFD      The socket's file descriptor to add to the list.
286   @param [in] pPort         The WSDT_PORT structure address
287   @param [out] pbDone       Address to receive the request completion status
288 
289   @retval EFI_SUCCESS       The request was successfully processed
290 
291 **/
292 EFI_STATUS
ConfigurationTablePage(IN int SocketFD,IN WSDT_PORT * pPort,OUT BOOLEAN * pbDone)293 ConfigurationTablePage (
294   IN int SocketFD,
295   IN WSDT_PORT * pPort,
296   OUT BOOLEAN * pbDone
297   )
298 {
299   EFI_CONFIGURATION_TABLE * pEnd;
300   EFI_CONFIGURATION_TABLE * pTable;
301   EFI_STATUS Status;
302 
303   DBG_ENTER ( );
304 
305   //
306   //  Send the system table page
307   //
308   for ( ; ; ) {
309     //
310     //  Send the page and table header
311     //
312     Status = TableHeader ( SocketFD, pPort, L"Configuration Tables", gST );
313     if ( EFI_ERROR ( Status )) {
314       break;
315     }
316 
317     //
318     //  Display the table size
319     //
320     Status = RowDecimalValue ( SocketFD,
321                                pPort,
322                                "Entries",
323                                gST->NumberOfTableEntries );
324     if ( EFI_ERROR ( Status )) {
325       break;
326     }
327 
328     //
329     //  Determine the location of the configuration tables
330     //
331     pTable = gST->ConfigurationTable;
332     pEnd = &pTable[ gST->NumberOfTableEntries ];
333     while ( pEnd > pTable ) {
334       Status = RowGuid ( SocketFD,
335                          pPort,
336                          "VendorGuid",
337                          &pTable->VendorGuid );
338       if ( EFI_ERROR ( Status )) {
339         break;
340       }
341       Status = RowPointer ( SocketFD,
342                             pPort,
343                             "VendorTable",
344                             (VOID *)pTable->VendorTable,
345                             NULL );
346       if ( EFI_ERROR ( Status )) {
347         break;
348       }
349 
350       //
351       //  Set the next row
352       //
353       pTable += 1;
354     }
355 
356     //
357     //  Build the table trailer
358     //
359     Status = TableTrailer ( SocketFD,
360                             pPort,
361                             pbDone );
362     break;
363   }
364 
365   //
366   //  Return the operation status
367   //
368   DBG_EXIT_STATUS ( Status );
369   return Status;
370 }
371