1 /**
2   @file
3   Display the handles in the system
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   Respond with the handles in the system
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 [out] pbDone       Address to receive the request completion status
25 
26   @retval EFI_SUCCESS       The request was successfully processed
27 
28 **/
29 EFI_STATUS
HandlePage(IN int SocketFD,IN WSDT_PORT * pPort,OUT BOOLEAN * pbDone)30 HandlePage (
31   IN int SocketFD,
32   IN WSDT_PORT * pPort,
33   OUT BOOLEAN * pbDone
34   )
35 {
36   INTN Digit;
37   INTN Entries;
38   INTN Index;
39   UINTN GuidCount;
40   UINTN LengthInBytes;
41   UINT8 * pDigit;
42   EFI_HANDLE * pHandleArray;
43   EFI_HANDLE * pHandle;
44   EFI_HANDLE * pHandleEnd;
45   EFI_GUID ** ppGuidArray;
46   EFI_GUID ** ppGuid;
47   EFI_GUID ** ppGuidEnd;
48   INTN Shift;
49   EFI_STATUS Status;
50   UINTN Value;
51   CONST UINTN cDigit [] = {
52     3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15 };
53 
54   DBG_ENTER ( );
55 
56   //
57   //  Send the handles page
58   //
59   for ( ; ; ) {
60     //
61     //  Send the page header
62     //
63     Status = HttpPageHeader ( SocketFD, pPort, L"Handle Database" );
64     if ( EFI_ERROR ( Status )) {
65       break;
66     }
67 
68     //
69     //  Build the table header
70     //
71     Status = HttpSendAnsiString ( SocketFD,
72                                   pPort,
73                                   "<h1>Handle Database</h1>\r\n"
74                                   "<table border=\"1\">\r\n"
75                                   "  <tr bgcolor=\"c0c0ff\"><th>Handle</th><th>Protocol Guids</th></tr>\r\n" );
76     if ( EFI_ERROR ( Status )) {
77       break;
78     }
79 
80     //
81     //  Determine the number of handles in the database
82     //
83     LengthInBytes = 0;
84     Status = gBS->LocateHandle ( AllHandles,
85                                  NULL,
86                                  NULL,
87                                  &LengthInBytes,
88                                  NULL );
89     if ( EFI_BUFFER_TOO_SMALL == Status ) {
90       //
91       //  Allocate space for the handles
92       //
93       Status = gBS->AllocatePool ( EfiRuntimeServicesData,
94                                    LengthInBytes,
95                                    (VOID **) &pHandleArray );
96       if ( !EFI_ERROR ( Status )) {
97         //
98         //  Get the list of handles
99         //
100         Status = gBS->LocateHandle ( AllHandles,
101                                      NULL,
102                                      NULL,
103                                      &LengthInBytes,
104                                      pHandleArray );
105         if ( !EFI_ERROR ( Status )) {
106           Entries = LengthInBytes / sizeof ( *pHandleArray );
107           pHandle = pHandleArray;
108           pHandleEnd = &pHandle [ Entries ];
109           while ( pHandleEnd > pHandle ) {
110             //
111             //  Build the table entry for this page
112             //
113             Status = HttpSendAnsiString ( SocketFD,
114                                           pPort,
115                                           "<tr><td><code>0x" );
116             if ( EFI_ERROR ( Status )) {
117               break;
118             }
119             Value = (UINTN) *pHandle;
120             for ( Shift = ( sizeof ( Shift ) << 3 ) - 4; 0 <= Shift; Shift -= 4 ) {
121               //
122               //  Convert the next address nibble to ANSI hex
123               //
124               Digit = (( Value >> Shift ) & 0xf ) | '0';
125               if ( '9' < Digit ) {
126                 Digit += 'a' - '0' - 10;
127               }
128 
129               //
130               //  Display the address digit
131               //
132               Status = HttpSendByte ( SocketFD,
133                                       pPort,
134                                       (UINT8) Digit );
135               if ( EFI_ERROR ( Status )) {
136                 break;
137               }
138             }
139             if ( EFI_ERROR ( Status )) {
140               break;
141             }
142 
143             //
144             //  Start the second column
145             //
146             Status = HttpSendAnsiString ( SocketFD,
147                                           pPort,
148                                           "</code></td><td><code>\r\n" );
149             if ( EFI_ERROR ( Status )) {
150               break;
151             }
152 
153             //
154             //  Determine the number of protocols connected to this handle
155             //
156             Status = gBS->ProtocolsPerHandle ( *pHandle,
157                                                &ppGuidArray,
158                                                &GuidCount );
159             if ( EFI_ERROR ( Status )) {
160               break;
161             }
162             ppGuid = ppGuidArray;
163             ppGuidEnd = &ppGuid [ GuidCount ];
164             while ( ppGuidEnd > ppGuid ) {
165               //
166               //  Display the guid
167               //
168               pDigit = (UINT8 *) *ppGuid;
169               for ( Index = 0; 16 > Index; Index++ ) {
170                 //
171                 //  Separate the portions of the GUID
172                 //  99E87DCF-6162-40c5-9FA1-32111F5197F7
173                 //
174                 if (( 4 == Index )
175                   || ( 6 == Index )
176                   || ( 8 == Index )
177                   || ( 10 == Index )) {
178                   Status = HttpSendByte ( SocketFD,
179                                           pPort,
180                                           '-' );
181                   if ( EFI_ERROR ( Status )) {
182                     break;
183                   }
184                 }
185 
186                 //
187                 //  Display the GUID digits
188                 //
189                 Value = pDigit [ cDigit [ Index ]];
190                 for ( Shift = 4; 0 <= Shift; Shift -= 4 ) {
191                   //
192                   //  Convert the next address nibble to ANSI hex
193                   //
194                   Digit = (( Value >> Shift ) & 0xf ) | '0';
195                   if ( '9' < Digit ) {
196                     Digit += 'a' - '0' - 10;
197                   }
198 
199                   //
200                   //  Display the address digit
201                   //
202                   Status = HttpSendByte ( SocketFD,
203                                           pPort,
204                                           (UINT8) Digit );
205                   if ( EFI_ERROR ( Status )) {
206                     break;
207                   }
208                 }
209                 if ( EFI_ERROR ( Status )) {
210                   break;
211                 }
212               }
213 
214               //
215               //  Separate each GUID
216               //
217               Status = HttpSendAnsiString ( SocketFD,
218                                             pPort,
219                                             "<br/>\r\n" );
220               if ( EFI_ERROR ( Status )) {
221                 break;
222               }
223 
224               //
225               //  Set the next protocol
226               //
227               ppGuid+= 1;
228             }
229 
230             //
231             //  Free the GUID array
232             //
233             gBS->FreePool ( ppGuidArray );
234             if ( EFI_ERROR ( Status )) {
235               break;
236             }
237 
238             //
239             //  End the row
240             //
241             Status = HttpSendAnsiString ( SocketFD,
242                                           pPort,
243                                           "</code></td></tr>\r\n" );
244             if ( EFI_ERROR ( Status )) {
245               break;
246             }
247 
248             //
249             //  Set the next handle
250             //
251             pHandle += 1;
252           }
253         }
254 
255         //
256         //  Done with the handle array
257         //
258         gBS->FreePool ( pHandleArray );
259       }
260     }
261 
262     //
263     //  Build the table trailer
264     //
265     Status = HttpSendAnsiString ( SocketFD,
266                                   pPort,
267                                   "</table>\r\n" );
268     if ( EFI_ERROR ( Status )) {
269       break;
270     }
271 
272     //
273     //  Send the page trailer
274     //
275     Status = HttpPageTrailer ( SocketFD, pPort, pbDone );
276     break;
277   }
278 
279   //
280   //  Return the operation status
281   //
282   DBG_EXIT_STATUS ( Status );
283   return Status;
284 }
285