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**/
29EFI_STATUS
30HandlePage (
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