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