Merged socket development branch:
[mirror_edk2.git] / AppPkg / Applications / Sockets / WebServer / HTTP.c
CommitLineData
7dc13291 1/*++\r
2 This file contains an 'Intel UEFI Application' and is\r
3 licensed for Intel CPUs and chipsets under the terms of your\r
4 license agreement with Intel or your vendor. This file may\r
5 be modified by the user, subject to additional terms of the\r
6 license agreement\r
7--*/\r
8/*++\r
9\r
10Copyright (c) 2011 Intel Corporation. All rights reserved\r
11This software and associated documentation (if any) is furnished\r
12under a license and may only be used or copied in accordance\r
13with the terms of the license. Except as permitted by such\r
14license, no part of this software or documentation may be\r
15reproduced, stored in a retrieval system, or transmitted in any\r
16form or by any means without the express written consent of\r
17Intel Corporation.\r
18\r
19--*/\r
20\r
21/** @file\r
22 HTTP processing for the web server.\r
23\r
24**/\r
25\r
26#include <WebServer.h>\r
27\r
28/**\r
29 Get a UTF-8 character from the buffer\r
30\r
31 @param [in] pData The address of the buffer containing the character\r
32 @param [out] ppData The address to receive the next character address\r
33\r
34 @return The character value\r
35\r
36**/\r
37INTN\r
38HttpCharGet (\r
39 IN UINT8 * pData,\r
40 IN UINT8 ** ppData\r
41 )\r
42{\r
43 INTN Data;\r
44 INTN Character;\r
45 INTN Control;\r
46 INTN Mask;\r
47\r
48 //\r
49 // Verify that there is some data left\r
50 //\r
51 if ( NULL == pData ) {\r
52 //\r
53 // No data to return\r
54 //\r
55 pData = NULL;\r
56 Character = 0;\r
57 }\r
58 else {\r
59 //\r
60 // Get the first portion of the character\r
61 //\r
62 Character = *pData++;\r
63 Control = Character;\r
64 Mask = 0xc0;\r
65\r
66 //\r
67 // Append the rest of the character\r
68 //\r
69 if ( 0 != ( Control & 0x80 )) {\r
70 while ( 0 != ( Control & 0x40 )) {\r
71 Character &= Mask;\r
72 Mask <<= 5;\r
73 Control <<= 1;\r
74 Character <<= 6;\r
75 Data = *pData++ & 0x3f;\r
76 if ( 0x80 != ( Data & 0xc0 )) {\r
77 //\r
78 // Invalid character\r
79 //\r
80 pData = NULL;\r
81 Character = 0;\r
82 break;\r
83 }\r
84 Character |= Data & 0x3f;\r
85 }\r
86 }\r
87 }\r
88\r
89 //\r
90 // Return the next character location and the character\r
91 //\r
92 *ppData = pData;\r
93 return Character;\r
94}\r
95\r
96\r
97/**\r
98 Transmit a portion of the HTTP response\r
99\r
100 @param [in] SocketFD The socket's file descriptor to add to the list.\r
101 @param [in] pPort The WSDT_PORT structure address\r
102\r
103 @retval EFI_SUCCESS The request was successfully processed\r
104\r
105**/\r
106EFI_STATUS\r
107HttpFlush (\r
108 IN int SocketFD,\r
109 IN WSDT_PORT * pPort\r
110 )\r
111{\r
112 INTN LengthInBytes;\r
113 UINT8 * pBuffer;\r
114 EFI_STATUS Status;\r
115\r
116 DBG_ENTER ( );\r
117\r
118 //\r
119 // Assume success\r
120 //\r
121 Status = EFI_SUCCESS;\r
122 pBuffer = &pPort->TxBuffer[0];\r
123 do {\r
124 //\r
125 // Attempt to send the data\r
126 //\r
127 LengthInBytes = send ( SocketFD,\r
128 pBuffer,\r
129 pPort->TxBytes,\r
130 0 );\r
131 if ( -1 != LengthInBytes ) {\r
132 //\r
133 // Account for the data sent\r
134 //\r
135 pBuffer += LengthInBytes;\r
136 pPort->TxBytes -= LengthInBytes;\r
137 }\r
138 else {\r
139 //\r
140 // Transmit error\r
141 //\r
142 Status = EFI_DEVICE_ERROR;\r
143 break;\r
144 }\r
145 } while ( 0 < pPort->TxBytes );\r
146\r
147 //\r
148 // Return the operation status\r
149 //\r
150 DBG_EXIT_STATUS ( Status );\r
151 return Status;\r
152}\r
153\r
154\r
155/**\r
156 Convert the ANSI character to lower case\r
157\r
158 @param [in] Character The character to convert to lower case.\r
159\r
160 @return The lower case character\r
161\r
162**/\r
163INTN\r
164HttpLowerCase (\r
165 IN INTN Character\r
166 )\r
167{\r
168 //\r
169 // Determine if the character is upper case\r
170 //\r
171 if (( 'A' <= Character ) && ( 'Z' >= Character )) {\r
172 Character += 'a' - 'A';\r
173 }\r
174\r
175 //\r
176 // Return the lower case value of the character\r
177 //\r
178 return Character;\r
179}\r
180\r
181\r
182/**\r
183 Match a Unicode string against a UTF-8 string\r
184\r
185 @param [in] pString A zero terminated Unicode string\r
186 @param [in] pData A zero terminated UTF-8 string\r
187 @param [in] bIgnoreCase TRUE if case is to be ignored\r
188\r
189 @return The difference between the last two characters tested.\r
190 Returns -1 for error.\r
191\r
192**/\r
193INTN\r
194HttpMatch (\r
195 IN UINT16 * pString,\r
196 IN UINT8 * pData,\r
197 IN BOOLEAN bIgnoreCase\r
198 )\r
199{\r
200 INTN Character1;\r
201 INTN Character2;\r
202 INTN Difference;\r
203\r
204 do {\r
205 //\r
206 // Get the character from the comparison string\r
207 //\r
208 Character1 = *pString++;\r
209\r
210 //\r
211 // Convert the character to lower case\r
212 //\r
213 if ( bIgnoreCase ) {\r
214 Character1 = HttpLowerCase ( Character1 );\r
215 }\r
216\r
217 //\r
218 // Get the character from the request\r
219 //\r
220 Character2 = HttpCharGet ( pData, &pData );\r
221 if ( NULL == pData ) {\r
222 //\r
223 // Error getting character\r
224 //\r
225 Difference = -1;\r
226 break;\r
227 }\r
228\r
229 //\r
230 // Convert the character to lower case\r
231 //\r
232 if ( bIgnoreCase ) {\r
233 Character2 = HttpLowerCase ( Character2 );\r
234 }\r
235\r
236 //\r
237 // Compare the characters\r
238 //\r
239 Difference = Character1 - Character2;\r
240 if ( 0 != Difference ) {\r
241 return Difference;\r
242 }\r
243 } while ( 0 != Character1 );\r
244\r
245 //\r
246 // Return the difference\r
247 //\r
248 return Difference;\r
249}\r
250\r
251\r
252/**\r
253 Buffer the HTTP page header\r
254\r
255 @param [in] SocketFD The socket's file descriptor to add to the list.\r
256 @param [in] pPort The WSDT_PORT structure address\r
257 @param [in] pTitle A zero terminated Unicode title string\r
258\r
259 @retval EFI_SUCCESS The request was successfully processed\r
260\r
261**/\r
262EFI_STATUS\r
263HttpPageHeader (\r
264 IN int SocketFD,\r
265 IN WSDT_PORT * pPort,\r
266 IN CONST CHAR16 * pTitle\r
267 )\r
268{\r
269 EFI_STATUS Status;\r
270\r
271 DBG_ENTER ( );\r
272\r
273 //\r
274 // Build the page header\r
275 //\r
276 for ( ; ; ) {\r
277 Status = HttpSendAnsiString ( SocketFD,\r
278 pPort,\r
279 "<!DOCTYPE "\r
280 "HTML "\r
281 "PUBLIC "\r
282 "\"-//W3C//DTD HTML 4.01 Transitional//EN\" "\r
283 "\"http://www.w3.org/TR/html4/loose.dtd\">\r\n" );\r
284 if ( EFI_ERROR ( Status )) {\r
285 break;\r
286 }\r
287 Status = HttpSendAnsiString ( SocketFD, pPort, "<html lang=\"en-US\">\r\n" );\r
288 if ( EFI_ERROR ( Status )) {\r
289 break;\r
290 }\r
291 if ( NULL != pTitle ) {\r
292 Status = HttpSendAnsiString ( SocketFD, pPort, " <head>\r\n" );\r
293 if ( EFI_ERROR ( Status )) {\r
294 break;\r
295 }\r
296 Status = HttpSendAnsiString ( SocketFD, pPort, " <title>" );\r
297 if ( EFI_ERROR ( Status )) {\r
298 break;\r
299 }\r
300 Status = HttpSendUnicodeString ( SocketFD, pPort, pTitle );\r
301 if ( EFI_ERROR ( Status )) {\r
302 break;\r
303 }\r
304 Status = HttpSendAnsiString ( SocketFD, pPort, "</title>\r\n" );\r
305 if ( EFI_ERROR ( Status )) {\r
306 break;\r
307 }\r
308 Status = HttpSendAnsiString ( SocketFD, pPort, " </head>\r\n" );\r
309 if ( EFI_ERROR ( Status )) {\r
310 break;\r
311 }\r
312 }\r
313 Status = HttpSendAnsiString ( SocketFD, pPort, " <body>\r\n" );\r
314 break;\r
315 }\r
316\r
317 //\r
318 // Return the operation status\r
319 //\r
320 DBG_EXIT_STATUS ( Status );\r
321 return Status;\r
322}\r
323\r
324\r
325/**\r
326 Respond with an error indicating that the page was not found\r
327\r
328 @param [in] SocketFD The socket's file descriptor to add to the list.\r
329 @param [in] pPort The WSDT_PORT structure address\r
330 @param [out] pbDone Address to receive the request completion status\r
331\r
332 @retval EFI_SUCCESS The request was successfully processed\r
333\r
334**/\r
335EFI_STATUS\r
336HttpPageNotFound (\r
337 IN int SocketFD,\r
338 IN WSDT_PORT * pPort,\r
339 IN BOOLEAN * pbDone\r
340 )\r
341{\r
342 EFI_STATUS Status;\r
343\r
344 DBG_ENTER ( );\r
345\r
346 //\r
347 // Send the page not found\r
348 //\r
349 for ( ; ; ) {\r
350 //\r
351 // Send the page header\r
352 //\r
353 Status = HttpPageHeader ( SocketFD, pPort, L"404 Not found" );\r
354 if ( EFI_ERROR ( Status )) {\r
355 break;\r
356 }\r
357\r
358 //\r
359 // Send the page body\r
360 //\r
361 Status = HttpSendAnsiString ( SocketFD,\r
362 pPort,\r
363 "ERROR <b>404</b><br />"\r
364 "Requested page is not available\r\n" );\r
365 if ( EFI_ERROR ( Status )) {\r
366 break;\r
367 }\r
368\r
369 //\r
370 // Send the page trailer\r
371 //\r
372 Status = HttpPageTrailer ( SocketFD, pPort, pbDone );\r
373 break;\r
374 }\r
375\r
376 //\r
377 // Return the operation status\r
378 //\r
379 DBG_EXIT_STATUS ( Status );\r
380 return Status;\r
381}\r
382\r
383\r
384/**\r
385 Buffer and send the HTTP page trailer\r
386\r
387 @param [in] SocketFD The socket's file descriptor to add to the list.\r
388 @param [in] pPort The WSDT_PORT structure address\r
389 @param [out] pbDone Address to receive the request completion status\r
390\r
391 @retval EFI_SUCCESS The request was successfully processed\r
392\r
393**/\r
394EFI_STATUS\r
395HttpPageTrailer (\r
396 IN int SocketFD,\r
397 IN WSDT_PORT * pPort,\r
398 IN BOOLEAN * pbDone\r
399 )\r
400{\r
401 int RetVal;\r
402 EFI_STATUS Status;\r
403 socklen_t LengthInBytes;\r
f6e5cdd5 404 struct sockaddr_in6 LocalAddress;\r
405 struct sockaddr_in6 RemoteAddress;\r
7dc13291 406\r
407 DBG_ENTER ( );\r
408\r
409 //\r
410 // Build the page header\r
411 //\r
412 for ( ; ; ) {\r
413 LengthInBytes = sizeof ( LocalAddress );\r
414 RetVal = getsockname ( SocketFD, (struct sockaddr *)&LocalAddress, &LengthInBytes );\r
415 if ( 0 == RetVal ) {\r
f6e5cdd5 416 LengthInBytes = sizeof ( LocalAddress );\r
7dc13291 417 RetVal = getpeername ( SocketFD, (struct sockaddr *)&RemoteAddress, &LengthInBytes );\r
418 if ( 0 == RetVal ) {\r
419 //\r
420 // Seperate the body from the trailer\r
421 //\r
f6e5cdd5 422 Status = HttpSendAnsiString ( SocketFD, pPort, " <hr>\r\n<code>" );\r
7dc13291 423 if ( EFI_ERROR ( Status )) {\r
424 break;\r
425 }\r
426\r
427 //\r
428 // Display the system addresses and the page transfer direction\r
429 //\r
430 Status = HttpSendIpAddress ( SocketFD, pPort, &LocalAddress );\r
431 if ( EFI_ERROR ( Status )) {\r
432 break;\r
433 }\r
434 Status = HttpSendAnsiString ( SocketFD, pPort, " --> " );\r
435 if ( EFI_ERROR ( Status )) {\r
436 break;\r
437 }\r
438 Status = HttpSendIpAddress ( SocketFD, pPort, &RemoteAddress );\r
439 if ( EFI_ERROR ( Status )) {\r
440 break;\r
441 }\r
f6e5cdd5 442 Status = HttpSendAnsiString ( SocketFD, pPort, "</code>\r\n" );\r
7dc13291 443 if ( EFI_ERROR ( Status )) {\r
444 break;\r
445 }\r
446 }\r
447 }\r
448\r
449 //\r
450 // Terminate the page\r
451 //\r
452 Status = HttpSendAnsiString ( SocketFD, pPort, " </body>\r\n" );\r
453 if ( EFI_ERROR ( Status )) {\r
454 break;\r
455 }\r
456 Status = HttpSendAnsiString ( SocketFD, pPort, " </html>\r\n" );\r
457 if ( EFI_ERROR ( Status )) {\r
458 break;\r
459 }\r
460\r
461 //\r
462 // Send the page trailer\r
463 //\r
464 Status = HttpFlush ( SocketFD, pPort );\r
465 if ( EFI_ERROR ( Status )) {\r
466 break;\r
467 }\r
468\r
469 //\r
470 // Mark the page as complete\r
471 //\r
472 *pbDone = TRUE;\r
473 break;\r
474 }\r
475\r
476 //\r
477 // Return the operation status\r
478 //\r
479 DBG_EXIT_STATUS ( Status );\r
480 return Status;\r
481}\r
482\r
483\r
484/**\r
485 Replace a space with a zero\r
486\r
487 @param [in] pData The request buffer address\r
488 @param [in] pEnd End of buffer address\r
489\r
490 @return The next character location\r
491\r
492**/\r
493UINT8 *\r
494HttpReplaceSpace (\r
495 IN UINT8 * pData,\r
496 IN UINT8 * pEnd\r
497 )\r
498{\r
499 INTN Character;\r
500 UINT8 * pSpace;\r
501\r
502 pSpace = pData;\r
503 while ( pEnd > pData ) {\r
504 //\r
505 // Get the character from the request\r
506 //\r
507 Character = HttpCharGet ( pData, &pData );\r
508 if ( ' ' == Character ) {\r
509 break;\r
510 }\r
511 pSpace = pData;\r
512 }\r
513\r
514 //\r
515 // Replace the space character with zero\r
516 //\r
517 ZeroMem ( pSpace, pData - pSpace );\r
518\r
519 //\r
520 // Return the next character location\r
521 //\r
522 return pData;\r
523}\r
524\r
525\r
526/**\r
527 Process an HTTP request\r
528\r
529 @param [in] SocketFD The socket's file descriptor to add to the list.\r
530 @param [in] pPort The WSDT_PORT structure address\r
531 @param [out] pbDone Address to receive the request completion status\r
532\r
533 @retval EFI_SUCCESS The request was successfully processed\r
534\r
535**/\r
536EFI_STATUS\r
537HttpRequest (\r
538 IN int SocketFD,\r
539 IN WSDT_PORT * pPort,\r
540 OUT BOOLEAN * pbDone\r
541 )\r
542{\r
543 UINT8 * pData;\r
544 UINT8 * pEnd;\r
545 CONST DT_PAGE * pPage;\r
546 CONST DT_PAGE * pPageEnd;\r
547 UINT8 * pVerb;\r
548 UINT8 * pVersion;\r
549 UINT8 * pWebPage;\r
550 EFI_STATUS Status;\r
551\r
552 DBG_ENTER ( );\r
553\r
554 //\r
555 // Assume the request is not finished\r
556 //\r
557 *pbDone = FALSE;\r
558 Status = EFI_SUCCESS;\r
559 for ( ; ; ) {\r
560\r
561 //\r
562 // Attempt to parse the command\r
563 //\r
564 pData = &pPort->Request[0];\r
59bc0593 565 pEnd = &pData[ pPort->RequestLength ];\r
7dc13291 566 pVerb = pData;\r
567 pWebPage = HttpReplaceSpace ( pVerb, pEnd );\r
568 if ( pEnd <= pWebPage ) {\r
569 break;\r
570 }\r
571 pVersion = HttpReplaceSpace ( pWebPage, pEnd );\r
572 if ( pEnd <= pVersion ) {\r
573 break;\r
574 }\r
575\r
576 //\r
577 // Validate the request\r
578 //\r
579 if ( 0 != HttpMatch ( L"GET", pVerb, TRUE )) {\r
580 //\r
581 // Invalid request type\r
582 //\r
583 DEBUG (( DEBUG_REQUEST,\r
584 "HTTP: Invalid verb\r\n" ));\r
585 Status = EFI_NOT_FOUND;\r
586 break;\r
587 }\r
588\r
589 //\r
590 // Walk the page table\r
591 //\r
592 pPage = &mPageList[0];\r
59bc0593 593 pPageEnd = &pPage[ mPageCount ];\r
7dc13291 594 while ( pPageEnd > pPage ) {\r
595 //\r
596 // Determine if the page was located\r
597 //\r
598 if ( 0 == HttpMatch ( pPage->pPageName, pWebPage, FALSE )) {\r
599 break;\r
600 }\r
601\r
602 //\r
603 // Set the next page\r
604 //\r
605 pPage += 1;\r
606 }\r
607 if ( pPageEnd <= pPage ) {\r
608 //\r
609 // The page was not found\r
610 //\r
611 DEBUG (( DEBUG_REQUEST,\r
612 "HTTP: Page not found in page table\r\n" ));\r
613 Status = EFI_NOT_FOUND;\r
614 break;\r
615 }\r
616\r
617 //\r
618 // Respond with the page contents\r
619 //\r
620 Status = pPage->pfnResponse ( SocketFD, pPort, pbDone );\r
621 break;\r
622 }\r
623\r
624 //\r
625 // Return page not found if necessary\r
626 //\r
627 if ( EFI_NOT_FOUND == Status ) {\r
628 Status = HttpPageNotFound ( SocketFD, pPort, pbDone );\r
629 }\r
630\r
631 //\r
632 // Return the operation status\r
633 //\r
634 DBG_EXIT_STATUS ( Status );\r
635 return Status;\r
636}\r
637\r
638\r
639/**\r
640 Buffer data for sending\r
641\r
642 @param [in] SocketFD The socket's file descriptor to add to the list.\r
643 @param [in] pPort The WSDT_PORT structure address\r
644 @param [in] LengthInBytes Length of valid data in the buffer\r
645 @param [in] pBuffer Buffer of data to send\r
646\r
647 @retval EFI_SUCCESS The request was successfully processed\r
648\r
649**/\r
650EFI_STATUS\r
651HttpSend (\r
652 IN int SocketFD,\r
653 IN WSDT_PORT * pPort,\r
654 IN size_t LengthInBytes,\r
655 IN CONST UINT8 * pBuffer\r
656 )\r
657{\r
658 size_t DataBytes;\r
659 size_t MaxBytes;\r
660 EFI_STATUS Status;\r
661\r
662 //\r
663 // Assume success\r
664 //\r
665 Status = EFI_SUCCESS;\r
666 do {\r
667 //\r
668 // Determine how much data fits into the buffer\r
669 //\r
670 MaxBytes = sizeof ( pPort->TxBuffer );\r
671 DataBytes = MaxBytes - pPort->TxBytes;\r
59bc0593 672 if ( DataBytes > LengthInBytes ) {\r
7dc13291 673 DataBytes = LengthInBytes;\r
674 }\r
675\r
676 //\r
677 // Copy the data into the buffer\r
678 //\r
59bc0593 679 CopyMem ( &pPort->TxBuffer[ pPort->TxBytes ],\r
7dc13291 680 pBuffer,\r
681 DataBytes );\r
682\r
683 //\r
684 // Account for the data copied\r
685 //\r
686 pPort->TxBytes += DataBytes;\r
687 LengthInBytes -= DataBytes;\r
688\r
689 //\r
690 // Transmit the buffer if it is full\r
691 //\r
692 if ( MaxBytes <= pPort->TxBytes ) {\r
693 Status = HttpFlush ( SocketFD, pPort );\r
694 }\r
695 } while (( EFI_SUCCESS == Status ) && ( 0 < LengthInBytes ));\r
696\r
697 //\r
698 // Return the operation status\r
699 //\r
700 return Status;\r
701}\r
702\r
703\r
704/**\r
705 Send an ANSI string\r
706\r
707 @param [in] SocketFD The socket's file descriptor to add to the list.\r
708 @param [in] pPort The WSDT_PORT structure address\r
709 @param [in] pString A zero terminated Unicode string\r
710\r
711 @retval EFI_SUCCESS The request was successfully processed\r
712\r
713**/\r
714EFI_STATUS\r
715HttpSendAnsiString (\r
716 IN int SocketFD,\r
717 IN WSDT_PORT * pPort,\r
718 IN CONST char * pString\r
719 )\r
720{\r
721 CONST char * pData;\r
722 EFI_STATUS Status;\r
723\r
724 //\r
725 // Assume success\r
726 //\r
727 Status = EFI_SUCCESS;\r
728\r
729 //\r
730 // Walk the characters in he string\r
731 //\r
732 pData = pString;\r
733 while ( 0 != *pData ) {\r
734 pData += 1;\r
735 }\r
736\r
737 //\r
738 // Send the string\r
739 //\r
740 Status = HttpSend ( SocketFD,\r
741 pPort,\r
742 pData - pString,\r
743 (CONST UINT8 *)pString );\r
744\r
745 //\r
746 // Return the operation status\r
747 //\r
748 return Status;\r
749}\r
750\r
751\r
752/**\r
753 Buffer a single byte\r
754\r
755 @param [in] SocketFD The socket's file descriptor to add to the list.\r
756 @param [in] pPort The WSDT_PORT structure address\r
757 @param [in] Data The data byte to send\r
758\r
759 @retval EFI_SUCCESS The request was successfully processed\r
760\r
761**/\r
762EFI_STATUS\r
763HttpSendByte (\r
764 IN int SocketFD,\r
765 IN WSDT_PORT * pPort,\r
766 IN UINT8 Data\r
767 )\r
768{\r
769 EFI_STATUS Status;\r
770\r
771 //\r
772 // Send the data byte\r
773 //\r
774 Status = HttpSend ( SocketFD,\r
775 pPort,\r
776 1,\r
777 &Data );\r
778\r
779 //\r
780 // Return the operation status\r
781 //\r
782 return Status;\r
783}\r
784\r
785\r
786/**\r
787 Display a character\r
788\r
789 @param [in] SocketFD The socket's file descriptor to add to the list.\r
790 @param [in] pPort The WSDT_PORT structure address\r
791 @param [in] Character Character to display\r
792 @param [in] pReplacement Replacement character string\r
793\r
794 @retval EFI_SUCCESS The request was successfully processed\r
795\r
796**/\r
797EFI_STATUS\r
798HttpSendCharacter (\r
799 IN int SocketFD,\r
800 IN WSDT_PORT * pPort,\r
801 IN CHAR8 Character,\r
802 IN CHAR8 * pReplacement\r
803 )\r
804{\r
805 EFI_STATUS Status;\r
806\r
807 //\r
808 // Determine if this is a printable character\r
809 //\r
810 if (( 0x20 <= Character ) && ( 0x7f > Character )) {\r
811 if ( '<' == Character ) {\r
812 //\r
813 // Replace with HTML equivalent\r
814 //\r
815 Status = HttpSendAnsiString ( SocketFD,\r
816 pPort,\r
817 "&lt;" );\r
818 }\r
819 else if ( '>' == Character ) {\r
820 //\r
821 // Replace with HTML equivalent\r
822 //\r
823 Status = HttpSendAnsiString ( SocketFD,\r
824 pPort,\r
825 "&gt;" );\r
826 }\r
827 else if ( '&' == Character ) {\r
828 //\r
829 // Replace with HTML equivalent\r
830 //\r
831 Status = HttpSendAnsiString ( SocketFD,\r
832 pPort,\r
833 "&amp;" );\r
834 }\r
835 else if ( '\"' == Character ) {\r
836 //\r
837 // Replace with HTML equivalent\r
838 //\r
839 Status = HttpSendAnsiString ( SocketFD,\r
840 pPort,\r
841 "&quot;" );\r
842 }\r
843 else {\r
844 //\r
845 // Display the character\r
846 //\r
847 Status = HttpSendByte ( SocketFD,\r
848 pPort,\r
849 Character );\r
850 }\r
851 }\r
852 else {\r
853 //\r
854 // Not a displayable character\r
855 //\r
856 Status = HttpSendAnsiString ( SocketFD,\r
857 pPort,\r
858 pReplacement );\r
859 }\r
860\r
861 //\r
862 // Return the operation status\r
863 //\r
864 return Status;\r
865}\r
866\r
867\r
868/**\r
869 Send a buffer dump\r
870\r
871 @param [in] SocketFD The socket's file descriptor to add to the list.\r
872 @param [in] pPort The WSDT_PORT structure address\r
873 @param [in] ByteCount The number of bytes to display\r
874 @param [in] pData Address of the byte array\r
875\r
876 @retval EFI_SUCCESS The request was successfully processed\r
877\r
878**/\r
879EFI_STATUS\r
880HttpSendDump (\r
881 IN int SocketFD,\r
882 IN WSDT_PORT * pPort,\r
883 IN UINTN ByteCount,\r
884 IN CONST UINT8 * pData\r
885 )\r
886{\r
887 INTN BytesToDisplay;\r
888 UINT8 Character;\r
889 INTN Index;\r
890 INTN InitialSpaces;\r
891 CONST UINT8 * pDataEnd;\r
892 CONST UINT8 * pEnd;\r
893 CONST UINT8 * pTemp;\r
894 EFI_STATUS Status;\r
895\r
896 //\r
897 // Use for/break instead of goto\r
898 //\r
899 for ( ; ; ) {\r
900 //\r
901 // Start the field value\r
902 //\r
903 Status = HttpSendAnsiString ( SocketFD,\r
904 pPort,\r
905 "<code>" );\r
906 if ( EFI_ERROR ( Status )) {\r
907 break;\r
908 }\r
909\r
910 //\r
911 // Walk the bytes to be displayed\r
912 //\r
59bc0593 913 pEnd = &pData[ ByteCount ];\r
7dc13291 914 while ( pEnd > pData ) {\r
915 //\r
916 // Display the address\r
917 //\r
918 Status = HttpSendHexBits ( SocketFD,\r
919 pPort,\r
920 sizeof ( pData ) * 8,\r
921 (UINT64)pData );\r
922 if ( EFI_ERROR ( Status )) {\r
923 break;\r
924 }\r
925\r
926 //\r
927 // Separate the address and data\r
928 //\r
929 Status = HttpSendByte ( SocketFD, pPort, ':' );\r
930 if ( EFI_ERROR ( Status )) {\r
931 break;\r
932 }\r
933\r
934 //\r
935 // Position the starting data correctly\r
936 //\r
937 InitialSpaces = (UINTN)pData;\r
938 InitialSpaces &= BYTES_ON_A_LINE - 1;\r
939 for ( Index = SPACES_ADDRESS_TO_DATA\r
940 + (( 2 + SPACES_BETWEEN_BYTES )\r
941 * InitialSpaces );\r
942 0 < Index; Index-- ) {\r
943 Status = HttpSendAnsiString ( SocketFD,\r
944 pPort,\r
945 "&nbsp;" );\r
946 if ( EFI_ERROR ( Status )) {\r
947 break;\r
948 }\r
949 }\r
950 if ( EFI_ERROR ( Status )) {\r
951 break;\r
952 }\r
953\r
954 //\r
955 // Display the data\r
956 //\r
957 BytesToDisplay = pEnd - pData;\r
958 if (( BYTES_ON_A_LINE - InitialSpaces ) < BytesToDisplay ) {\r
959 BytesToDisplay = BYTES_ON_A_LINE - InitialSpaces;\r
960 }\r
59bc0593 961 pDataEnd = &pData[ BytesToDisplay ];\r
7dc13291 962 pTemp = pData;\r
963 while ( pDataEnd > pTemp ) {\r
964 Status = HttpSendHexBits ( SocketFD,\r
965 pPort,\r
966 8,\r
967 *pTemp++ );\r
968 if ( EFI_ERROR ( Status )) {\r
969 break;\r
970 }\r
971\r
972 //\r
973 // Separate the data bytes\r
974 //\r
975 for ( Index = SPACES_BETWEEN_BYTES; 0 < Index; Index-- ) {\r
976 Status = HttpSendAnsiString ( SocketFD,\r
977 pPort,\r
978 "&nbsp;" );\r
979 if ( EFI_ERROR ( Status )) {\r
980 break;\r
981 }\r
982 }\r
983 if ( EFI_ERROR ( Status )) {\r
984 break;\r
985 }\r
986 }\r
987 if ( EFI_ERROR ( Status )) {\r
988 break;\r
989 }\r
990\r
991 //\r
992 // Separate the data from the ASCII display\r
993 //\r
994 for ( Index = (( 2 + SPACES_BETWEEN_BYTES )\r
995 * ( BYTES_ON_A_LINE - BytesToDisplay - InitialSpaces ))\r
996 - SPACES_BETWEEN_BYTES\r
997 + SPACES_DATA_TO_ASCII\r
998 + InitialSpaces;\r
999 0 < Index; Index-- ) {\r
1000 Status = HttpSendAnsiString ( SocketFD,\r
1001 pPort,\r
1002 "&nbsp;" );\r
1003 if ( EFI_ERROR ( Status )) {\r
1004 break;\r
1005 }\r
1006 }\r
1007 if ( EFI_ERROR ( Status )) {\r
1008 break;\r
1009 }\r
1010\r
1011 //\r
1012 // Display the ASCII data\r
1013 //\r
1014 while ( pDataEnd > pData ) {\r
1015 Character = *pData++;\r
1016 Status = HttpSendCharacter ( SocketFD,\r
1017 pPort,\r
1018 Character,\r
1019 "." );\r
1020 if ( EFI_ERROR ( Status )) {\r
1021 break;\r
1022 }\r
1023 }\r
1024 if ( EFI_ERROR ( Status )) {\r
1025 break;\r
1026 }\r
1027\r
1028 //\r
1029 // Terminate the line\r
1030 //\r
1031 Status = HttpSendAnsiString ( SocketFD,\r
1032 pPort,\r
1033 "<br/>\r\n" );\r
1034 if ( EFI_ERROR ( Status )) {\r
1035 break;\r
1036 }\r
1037 }\r
1038\r
1039 //\r
1040 // Terminate the field value and row\r
1041 //\r
1042 Status = HttpSendAnsiString ( SocketFD,\r
1043 pPort,\r
1044 "</code>\r\n" );\r
1045 break;\r
1046 }\r
1047\r
1048 //\r
1049 // Return the operation status\r
1050 //\r
1051 return Status;\r
1052}\r
1053\r
1054\r
1055/**\r
1056 Display a row containing a GUID value\r
1057\r
1058 @param [in] SocketFD The socket's file descriptor to add to the list.\r
1059 @param [in] pPort The WSDT_PORT structure address\r
1060 @param [in] pGuid Address of the GUID to display\r
1061\r
1062 @retval EFI_SUCCESS The request was successfully processed\r
1063\r
1064**/\r
1065EFI_STATUS\r
1066HttpSendGuid (\r
1067 IN int SocketFD,\r
1068 IN WSDT_PORT * pPort,\r
1069 IN CONST EFI_GUID * pGuid\r
1070 )\r
1071{\r
1072 UINT32 Index;\r
1073 EFI_STATUS Status;\r
1074\r
1075 DBG_ENTER ( );\r
1076\r
1077 //\r
1078 // Use for/break instead of goto\r
1079 //\r
1080 for ( ; ; ) {\r
1081 //\r
1082 // Display the GUID in a form found in the code\r
1083 //\r
1084 // E.g. 0xca16005f, 0x11ec, 0x4bdc, { 0x99, 0x97, 0x27, 0x2c, 0xa9, 0xba, 0x15, 0xe5 }\r
1085 //\r
1086\r
1087 //\r
1088 // Display the first 32 bits\r
1089 //\r
1090 Status = HttpSendAnsiString ( SocketFD,\r
1091 pPort,\r
1092 "0x" );\r
1093 if ( EFI_ERROR ( Status )) {\r
1094 break;\r
1095 }\r
1096 Status = HttpSendHexBits ( SocketFD,\r
1097 pPort,\r
1098 32,\r
1099 pGuid->Data1 );\r
1100 if ( EFI_ERROR ( Status )) {\r
1101 break;\r
1102 }\r
1103\r
1104 //\r
1105 // Display the second 16 bits\r
1106 //\r
1107 Status = HttpSendAnsiString ( SocketFD,\r
1108 pPort,\r
1109 ", 0x" );\r
1110 if ( EFI_ERROR ( Status )) {\r
1111 break;\r
1112 }\r
1113 Status = HttpSendHexBits ( SocketFD,\r
1114 pPort,\r
1115 16,\r
1116 pGuid->Data2 );\r
1117 if ( EFI_ERROR ( Status )) {\r
1118 break;\r
1119 }\r
1120\r
1121 //\r
1122 // Display the thrid 16 bits\r
1123 //\r
1124 Status = HttpSendAnsiString ( SocketFD,\r
1125 pPort,\r
1126 ", 0x" );\r
1127 if ( EFI_ERROR ( Status )) {\r
1128 break;\r
1129 }\r
1130 Status = HttpSendHexBits ( SocketFD,\r
1131 pPort,\r
1132 16,\r
1133 pGuid->Data3 );\r
1134 if ( EFI_ERROR ( Status )) {\r
1135 break;\r
1136 }\r
1137\r
1138 //\r
1139 // Place the last 64 bits in braces\r
1140 //\r
1141 Status = HttpSendAnsiString ( SocketFD,\r
1142 pPort,\r
1143 ", { 0x" );\r
1144 if ( EFI_ERROR ( Status )) {\r
1145 break;\r
1146 }\r
1147 for ( Index = 0; 7 >= Index; Index++ ) {\r
1148 //\r
1149 // Display the next 8 bits\r
1150 //\r
1151 Status = HttpSendHexBits ( SocketFD,\r
1152 pPort,\r
1153 8,\r
59bc0593 1154 pGuid->Data4[ Index ]);\r
7dc13291 1155 if ( EFI_ERROR ( Status )) {\r
1156 break;\r
1157 }\r
1158\r
1159 //\r
1160 // Separate the bytes\r
1161 //\r
1162 Status = HttpSendAnsiString ( SocketFD,\r
1163 pPort,\r
1164 ( 7 != Index ) ? ", 0x" : " }" );\r
1165 if ( EFI_ERROR ( Status )) {\r
1166 break;\r
1167 }\r
1168 }\r
1169 break;\r
1170 }\r
1171\r
1172 //\r
1173 // Return the operation status\r
1174 //\r
1175 DBG_EXIT_STATUS ( Status );\r
1176 return Status;\r
1177}\r
1178\r
1179\r
1180/**\r
1181 Output a hex value to the HTML page\r
1182\r
1183 @param [in] SocketFD Socket file descriptor\r
1184 @param [in] pPort The WSDT_PORT structure address\r
1185 @param [in] Bits Number of bits to display\r
1186 @param [in] Value Value to display\r
1187\r
1188 @retval EFI_SUCCESS Successfully displayed the address\r
1189**/\r
1190EFI_STATUS\r
1191HttpSendHexBits (\r
1192 IN int SocketFD,\r
1193 IN WSDT_PORT * pPort,\r
1194 IN INT32 Bits,\r
1195 IN UINT64 Value\r
1196 )\r
1197{\r
1198 UINT32 Digit;\r
1199 INT32 Shift;\r
1200 EFI_STATUS Status;\r
1201\r
1202 //\r
1203 // Assume success\r
1204 //\r
1205 Status = EFI_SUCCESS;\r
1206\r
1207 //\r
1208 // Walk the list of divisors\r
1209 //\r
1210 Shift = (( Bits + 3 ) & ( ~3 )) - 4;\r
1211 while ( 0 <= Shift ) {\r
1212 //\r
1213 // Determine the next digit\r
1214 //\r
1215 Digit = (UINT32)(( Value >> Shift ) & 0xf );\r
1216 if ( 10 <= Digit ) {\r
f6e5cdd5 1217 Digit += 'a' - '0' - 10;\r
7dc13291 1218 }\r
1219\r
1220 //\r
1221 // Display the digit\r
1222 //\r
1223 Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Digit ));\r
1224 if ( EFI_ERROR ( Status )) {\r
1225 break;\r
1226 }\r
1227\r
1228 //\r
1229 // Set the next shift\r
1230 //\r
1231 Shift -= 4;\r
1232 }\r
1233\r
1234 //\r
1235 // Return the operation status\r
1236 //\r
1237 return Status;\r
1238}\r
1239\r
1240\r
1241/**\r
1242 Output a hex value to the HTML page\r
1243\r
1244 @param [in] SocketFD Socket file descriptor\r
1245 @param [in] pPort The WSDT_PORT structure address\r
1246 @param [in] Value Value to display\r
1247\r
1248 @retval EFI_SUCCESS Successfully displayed the address\r
1249**/\r
1250EFI_STATUS\r
1251HttpSendHexValue (\r
1252 IN int SocketFD,\r
1253 IN WSDT_PORT * pPort,\r
1254 IN UINT64 Value\r
1255 )\r
1256{\r
1257 BOOLEAN bDisplayZeros;\r
1258 UINT32 Digit;\r
1259 INT32 Shift;\r
1260 EFI_STATUS Status;\r
1261\r
1262 //\r
1263 // Assume success\r
1264 //\r
1265 Status = EFI_SUCCESS;\r
1266\r
1267 //\r
1268 // Walk the list of divisors\r
1269 //\r
1270 bDisplayZeros = FALSE;\r
1271 Shift = 60;\r
1272 do {\r
1273 //\r
1274 // Determine the next digit\r
1275 //\r
1276 Digit = (UINT32)(( Value >> Shift ) & 0xf );\r
1277 if ( 10 <= Digit ) {\r
f6e5cdd5 1278 Digit += 'a' - '0' - 10;\r
7dc13291 1279 }\r
1280\r
1281 //\r
1282 // Suppress leading zeros\r
1283 //\r
1284 if (( 0 != Digit ) || bDisplayZeros || ( 0 == Shift )) {\r
1285 bDisplayZeros = TRUE;\r
1286\r
1287 //\r
1288 // Display the digit\r
1289 //\r
1290 Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Digit ));\r
1291 if ( EFI_ERROR ( Status )) {\r
1292 break;\r
1293 }\r
1294 }\r
1295\r
1296 //\r
1297 // Set the next shift\r
1298 //\r
1299 Shift -= 4;\r
1300 } while ( 0 <= Shift );\r
1301\r
1302 //\r
1303 // Return the operation status\r
1304 //\r
1305 return Status;\r
1306}\r
1307\r
1308\r
f6e5cdd5 1309/**\r
1310 Output an IP6 address value to the HTML page\r
1311\r
1312 @param [in] SocketFD Socket file descriptor\r
1313 @param [in] pPort The WSDT_PORT structure address\r
1314 @param [in] Value Value to display\r
1315 @param [in] bFirstValue TRUE if first value\r
1316 @param [in] bLastValue TRUE if last value\r
1317 @param [in] bZeroSuppression TRUE while zeros are being suppressed\r
1318 @param [in] pbZeroSuppression Address to receive TRUE when zero suppression\r
1319 has started, use NULL if next colon value not\r
1320 needed.\r
1321\r
1322 @retval EFI_SUCCESS Successfully displayed the address\r
1323**/\r
1324EFI_STATUS\r
1325HttpSendIp6Value (\r
1326 IN int SocketFD,\r
1327 IN WSDT_PORT * pPort,\r
1328 IN UINT16 Value,\r
1329 IN BOOLEAN bFirstValue,\r
1330 IN BOOLEAN bLastValue,\r
1331 IN BOOLEAN bZeroSuppression,\r
1332 IN BOOLEAN * pbZeroSuppression\r
1333 )\r
1334{\r
1335 BOOLEAN bZeroSuppressionStarting;\r
1336 UINT32 Digit;\r
1337 EFI_STATUS Status;\r
1338\r
1339 //\r
1340 // Use break instead of goto\r
1341 //\r
1342 bZeroSuppressionStarting = FALSE;\r
1343 Status = EFI_SUCCESS;\r
1344 for ( ; ; ) {\r
1345 //\r
1346 // Display the leading colon if necessary\r
1347 //\r
1348 if ( bZeroSuppression && ( bLastValue || ( 0 != Value ))) {\r
1349 Status = HttpSendByte ( SocketFD, pPort, ':' );\r
1350 if ( EFI_ERROR ( Status )) {\r
1351 break;\r
1352 }\r
1353 }\r
1354\r
1355 //\r
1356 // Skip over a series of zero values\r
1357 //\r
1358 bZeroSuppressionStarting = (BOOLEAN)( 0 == Value );\r
1359 if ( !bZeroSuppressionStarting ) {\r
1360 //\r
1361 // Display the value\r
1362 //\r
1363 Digit = ( Value >> 4 ) & 0xf;\r
1364 Status = HttpSendHexValue ( SocketFD,\r
1365 pPort,\r
1366 Digit );\r
1367 if ( EFI_ERROR ( Status )) {\r
1368 break;\r
1369 }\r
1370 Digit = Value & 0xf;\r
1371 Status = HttpSendHexValue ( SocketFD,\r
1372 pPort,\r
1373 Digit );\r
1374 if ( EFI_ERROR ( Status )) {\r
1375 break;\r
1376 }\r
1377 Digit = ( Value >> 12 ) & 0xf;\r
1378 Status = HttpSendHexValue ( SocketFD,\r
1379 pPort,\r
1380 Digit );\r
1381 if ( EFI_ERROR ( Status )) {\r
1382 break;\r
1383 }\r
1384 Digit = ( Value >> 8 ) & 0xf;\r
1385 Status = HttpSendHexValue ( SocketFD,\r
1386 pPort,\r
1387 Digit );\r
1388 if ( EFI_ERROR ( Status )) {\r
1389 break;\r
1390 }\r
1391 }\r
1392\r
1393 //\r
1394 // Display the trailing colon if necessary\r
1395 //\r
1396 if (( !bLastValue ) && ( bFirstValue || ( 0 != Value ))) {\r
1397 Status = HttpSendByte ( SocketFD, pPort, ':' );\r
1398 }\r
1399 break;\r
1400 }\r
1401\r
1402 //\r
1403 // Return the next colon display\r
1404 if ( NULL != pbZeroSuppression ) {\r
1405 *pbZeroSuppression = bZeroSuppressionStarting;\r
1406 }\r
1407\r
1408 //\r
1409 // Return the operation status\r
1410 //\r
1411 return Status;\r
1412}\r
1413\r
1414\r
7dc13291 1415/**\r
1416 Output an IP address to the HTML page\r
1417\r
1418 @param [in] SocketFD Socket file descriptor\r
1419 @param [in] pPort The WSDT_PORT structure address\r
1420 @param [in] pAddress Address of the socket address\r
1421\r
1422 @retval EFI_SUCCESS Successfully displayed the address\r
1423**/\r
1424EFI_STATUS\r
1425HttpSendIpAddress (\r
1426 IN int SocketFD,\r
1427 IN WSDT_PORT * pPort,\r
f6e5cdd5 1428 IN struct sockaddr_in6 * pAddress\r
7dc13291 1429 )\r
1430{\r
f6e5cdd5 1431 BOOLEAN bZeroSuppression;\r
1432 UINT32 Index;\r
1433 struct sockaddr_in * pIpv4;\r
1434 struct sockaddr_in6 * pIpv6;\r
1435 UINT16 PortNumber;\r
7dc13291 1436 EFI_STATUS Status;\r
1437\r
1438 //\r
f6e5cdd5 1439 // Use break instead of goto\r
1440 //\r
1441 for ( ; ; ) {\r
1442 //\r
1443 // Determine the type of address\r
1444 //\r
1445 if ( AF_INET6 == pAddress->sin6_family ) {\r
1446 pIpv6 = pAddress;\r
1447\r
1448 //\r
1449 // Display the address in RFC2732 format\r
1450 //\r
1451 bZeroSuppression = FALSE;\r
1452 Status = HttpSendByte ( SocketFD, pPort, '[' );\r
1453 if ( EFI_ERROR ( Status )) {\r
1454 break;\r
1455 }\r
1456 for ( Index = 0; 8 > Index; Index++ ) {\r
1457 Status = HttpSendIp6Value ( SocketFD,\r
1458 pPort,\r
1459 pIpv6->sin6_addr.__u6_addr.__u6_addr16[ Index ],\r
1460 (BOOLEAN)( 0 == Index ),\r
1461 (BOOLEAN)( 7 == Index ),\r
1462 bZeroSuppression,\r
1463 &bZeroSuppression );\r
1464 if ( EFI_ERROR ( Status )) {\r
1465 break;\r
7dc13291 1466 }\r
1467 }\r
f6e5cdd5 1468 if ( EFI_ERROR ( Status )) {\r
1469 break;\r
1470 }\r
1471\r
1472 //\r
1473 // Separate the port number\r
1474 //\r
1475 Status = HttpSendByte ( SocketFD, pPort, ']' );\r
1476\r
1477 //\r
1478 // Get the port number\r
1479 //\r
1480 PortNumber = pIpv6->sin6_port;\r
7dc13291 1481 }\r
f6e5cdd5 1482 else {\r
1483 //\r
1484 // Output the IPv4 address\r
1485 //\r
1486 pIpv4 = (struct sockaddr_in *)pAddress;\r
1487 Status = HttpSendValue ( SocketFD, pPort, (UINT8)pIpv4->sin_addr.s_addr );\r
1488 if ( EFI_ERROR ( Status )) {\r
1489 break;\r
1490 }\r
1491 Status = HttpSendByte ( SocketFD, pPort, '.' );\r
1492 if ( EFI_ERROR ( Status )) {\r
1493 break;\r
1494 }\r
1495 Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pIpv4->sin_addr.s_addr >> 8 ));\r
1496 if ( EFI_ERROR ( Status )) {\r
1497 break;\r
1498 }\r
1499 Status = HttpSendByte ( SocketFD, pPort, '.' );\r
1500 if ( EFI_ERROR ( Status )) {\r
1501 break;\r
1502 }\r
1503 Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pIpv4->sin_addr.s_addr >> 16 ));\r
1504 if ( EFI_ERROR ( Status )) {\r
1505 break;\r
1506 }\r
1507 Status = HttpSendByte ( SocketFD, pPort, '.' );\r
1508 if ( EFI_ERROR ( Status )) {\r
1509 break;\r
1510 }\r
1511 Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pIpv4->sin_addr.s_addr >> 24 ));\r
1512\r
1513 //\r
1514 // Get the port number\r
1515 //\r
1516 PortNumber = pIpv4->sin_port;\r
1517 }\r
1518 if ( EFI_ERROR ( Status )) {\r
1519 break;\r
1520 }\r
1521\r
1522 //\r
1523 // Display the port number\r
1524 //\r
1525 Status = HttpSendByte ( SocketFD, pPort, ':' );\r
1526 if ( EFI_ERROR ( Status )) {\r
1527 break;\r
1528 }\r
1529 Status = HttpSendValue ( SocketFD, pPort, htons ( PortNumber ));\r
1530 break;\r
7dc13291 1531 }\r
1532\r
1533 //\r
1534 // Return the operation status\r
1535 //\r
1536 return Status;\r
1537}\r
1538\r
1539\r
1540/**\r
1541 Send a Unicode string\r
1542\r
1543 @param [in] SocketFD The socket's file descriptor to add to the list.\r
1544 @param [in] pPort The WSDT_PORT structure address\r
1545 @param [in] pString A zero terminated Unicode string\r
1546\r
1547 @retval EFI_SUCCESS The request was successfully processed\r
1548\r
1549**/\r
1550EFI_STATUS\r
1551HttpSendUnicodeString (\r
1552 IN int SocketFD,\r
1553 IN WSDT_PORT * pPort,\r
1554 IN CONST UINT16 * pString\r
1555 )\r
1556{\r
1557 UINT8 Data;\r
1558 UINT16 Character;\r
1559 EFI_STATUS Status;\r
1560\r
1561 //\r
1562 // Assume success\r
1563 //\r
1564 Status = EFI_SUCCESS;\r
1565\r
1566 //\r
1567 // Walk the characters in he string\r
1568 //\r
1569 while ( 0 != ( Character = *pString++ )) {\r
1570 //\r
1571 // Convert the character to UTF-8\r
1572 //\r
1573 if ( 0 != ( Character & 0xf800 )) {\r
1574 //\r
1575 // Send the upper 4 bits\r
1576 //\r
1577 Data = (UINT8)(( Character >> 12 ) & 0xf );\r
1578 Data |= 0xe0;\r
1579 Status = HttpSendByte ( SocketFD,\r
1580 pPort,\r
1581 Data );\r
1582 if ( EFI_ERROR ( Status )) {\r
1583 break;\r
1584 }\r
1585\r
1586 //\r
1587 // Send the next 6 bits\r
1588 //\r
1589 Data = (UINT8)(( Character >> 6 ) & 0x3f );\r
1590 Data |= 0x80;\r
1591 Status = HttpSendByte ( SocketFD,\r
1592 pPort,\r
1593 Data );\r
1594 if ( EFI_ERROR ( Status )) {\r
1595 break;\r
1596 }\r
1597\r
1598 //\r
1599 // Send the last 6 bits\r
1600 //\r
1601 Data = (UINT8)( Character & 0x3f );\r
1602 Data |= 0x80;\r
1603 }\r
1604 else if ( 0 != ( Character & 0x0780 )) {\r
1605 //\r
1606 // Send the upper 5 bits\r
1607 //\r
1608 Data = (UINT8)(( Character >> 6 ) & 0x1f );\r
1609 Data |= 0xc0;\r
1610 Status = HttpSendByte ( SocketFD,\r
1611 pPort,\r
1612 Data );\r
1613 if ( EFI_ERROR ( Status )) {\r
1614 break;\r
1615 }\r
1616\r
1617 //\r
1618 // Send the last 6 bits\r
1619 //\r
1620 Data = (UINT8)( Character & 0x3f );\r
1621 Data |= 0x80;\r
1622 }\r
1623 else {\r
1624 Data = (UINT8)( Character & 0x7f );\r
1625 }\r
1626\r
1627 //\r
1628 // Send the last data byte\r
1629 //\r
1630 Status = HttpSendByte ( SocketFD,\r
1631 pPort,\r
1632 Data );\r
1633 if ( EFI_ERROR ( Status )) {\r
1634 break;\r
1635 }\r
1636 }\r
1637\r
1638 //\r
1639 // Return the operation status\r
1640 //\r
1641 return Status;\r
1642}\r
1643\r
1644\r
1645/**\r
1646 Output a value to the HTML page\r
1647\r
1648 @param [in] SocketFD Socket file descriptor\r
1649 @param [in] pPort The WSDT_PORT structure address\r
1650 @param [in] Value Value to display\r
1651\r
1652 @retval EFI_SUCCESS Successfully displayed the address\r
1653**/\r
1654EFI_STATUS\r
1655HttpSendValue (\r
1656 IN int SocketFD,\r
1657 IN WSDT_PORT * pPort,\r
1658 IN UINT64 Value\r
1659 )\r
1660{\r
1661 BOOLEAN bDisplayZeros;\r
1662 UINT64 Digit;\r
1663 CONST UINT64 * pEnd;\r
1664 CONST UINT64 * pDivisor;\r
59bc0593 1665 CONST UINT64 pDivisors[ ] = {\r
7dc13291 1666 10000000000000000000L,\r
1667 1000000000000000000L,\r
1668 100000000000000000L,\r
1669 10000000000000000L,\r
1670 1000000000000000L,\r
1671 100000000000000L,\r
1672 10000000000000L,\r
1673 1000000000000L,\r
1674 100000000000L,\r
1675 10000000000L,\r
1676 1000000000L,\r
1677 100000000L,\r
1678 10000000L,\r
1679 1000000L,\r
1680 100000L,\r
1681 10000L,\r
1682 1000L,\r
1683 100L,\r
1684 10L\r
1685 };\r
1686 EFI_STATUS Status;\r
1687 UINT64 Temp;\r
1688\r
1689 //\r
1690 // Assume success\r
1691 //\r
1692 Status = EFI_SUCCESS;\r
1693\r
1694 //\r
1695 // Walk the list of divisors\r
1696 //\r
1697 bDisplayZeros = FALSE;\r
1698 pDivisor = &pDivisors[0];\r
59bc0593 1699 pEnd = &pDivisor[ sizeof ( pDivisors ) / sizeof ( pDivisors[0])];\r
7dc13291 1700 while ( pEnd > pDivisor ) {\r
1701 //\r
1702 // Determine the next digit\r
1703 //\r
1704 Digit = Value / *pDivisor;\r
1705\r
1706 //\r
1707 // Suppress leading zeros\r
1708 //\r
1709 if (( 0 != Digit ) || bDisplayZeros ) {\r
1710 bDisplayZeros = TRUE;\r
1711\r
1712 //\r
1713 // Display the digit\r
1714 //\r
1715 Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Digit ));\r
1716 if ( EFI_ERROR ( Status )) {\r
1717 break;\r
1718 }\r
1719\r
1720 //\r
1721 // Determine the remainder\r
1722 //\r
1723 Temp = *pDivisor * Digit;\r
1724 Value -= Temp;\r
1725 }\r
1726\r
1727 //\r
1728 // Set the next divisor\r
1729 //\r
1730 pDivisor += 1;\r
1731 }\r
1732\r
1733 //\r
1734 // Display the final digit\r
1735 //\r
1736 if ( !EFI_ERROR ( Status )) {\r
1737 Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Value ));\r
1738 }\r
1739\r
1740 //\r
1741 // Return the operation status\r
1742 //\r
1743 return Status;\r
1744}\r