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