TianoCore EDK2 master
Loading...
Searching...
No Matches
DxeHttpIoLib.c
Go to the documentation of this file.
1
8#include <Uefi.h>
9
10#include <Protocol/Http.h>
11
12#include <Library/BaseLib.h>
14#include <Library/DebugLib.h>
15#include <Library/HttpIoLib.h>
17#include <Library/PrintLib.h>
19
26VOID
27EFIAPI
29 IN VOID *Context
30 )
31{
32 *((BOOLEAN *)Context) = TRUE;
33}
34
42VOID
43EFIAPI
45 IN EFI_EVENT Event,
46 IN VOID *Context
47 )
48{
49 //
50 // Request HttpIoNotifyDpc as a DPC at TPL_CALLBACK
51 //
52 QueueDpc (TPL_CALLBACK, HttpIoNotifyDpc, Context);
53}
54
61VOID
63 IN HTTP_IO *HttpIo
64 )
65{
67 EFI_EVENT Event;
68
69 if (HttpIo == NULL) {
70 return;
71 }
72
73 Event = HttpIo->ReqToken.Event;
74 if (Event != NULL) {
75 gBS->CloseEvent (Event);
76 }
77
78 Event = HttpIo->RspToken.Event;
79 if (Event != NULL) {
80 gBS->CloseEvent (Event);
81 }
82
83 Event = HttpIo->TimeoutEvent;
84 if (Event != NULL) {
85 gBS->CloseEvent (Event);
86 }
87
88 Http = HttpIo->Http;
89 if (Http != NULL) {
90 Http->Configure (Http, NULL);
91 gBS->CloseProtocol (
92 HttpIo->Handle,
93 &gEfiHttpProtocolGuid,
94 HttpIo->Image,
95 HttpIo->Controller
96 );
97 }
98
100 HttpIo->Controller,
101 HttpIo->Image,
102 &gEfiHttpServiceBindingProtocolGuid,
103 HttpIo->Handle
104 );
105}
106
131 IN EFI_HANDLE Image,
132 IN EFI_HANDLE Controller,
133 IN UINT8 IpVersion,
134 IN HTTP_IO_CONFIG_DATA *ConfigData OPTIONAL,
135 IN HTTP_IO_CALLBACK Callback,
136 IN VOID *Context,
137 OUT HTTP_IO *HttpIo
138 )
139{
140 EFI_STATUS Status;
141 EFI_HTTP_CONFIG_DATA HttpConfigData;
142 EFI_HTTPv4_ACCESS_POINT Http4AccessPoint;
143 EFI_HTTPv6_ACCESS_POINT Http6AccessPoint;
144 EFI_HTTP_PROTOCOL *Http;
145 EFI_EVENT Event;
146
147 if ((Image == NULL) || (Controller == NULL) || (HttpIo == NULL)) {
148 return EFI_INVALID_PARAMETER;
149 }
150
151 if ((IpVersion != IP_VERSION_4) && (IpVersion != IP_VERSION_6)) {
152 return EFI_UNSUPPORTED;
153 }
154
155 ZeroMem (HttpIo, sizeof (HTTP_IO));
156 ZeroMem (&HttpConfigData, sizeof (EFI_HTTP_CONFIG_DATA));
157
158 //
159 // Create the HTTP child instance and get the HTTP protocol.
160 //
161 Status = NetLibCreateServiceChild (
162 Controller,
163 Image,
164 &gEfiHttpServiceBindingProtocolGuid,
165 &HttpIo->Handle
166 );
167 if (EFI_ERROR (Status)) {
168 return Status;
169 }
170
171 Status = gBS->OpenProtocol (
172 HttpIo->Handle,
173 &gEfiHttpProtocolGuid,
174 (VOID **)&Http,
175 Image,
176 Controller,
177 EFI_OPEN_PROTOCOL_BY_DRIVER
178 );
179 if (EFI_ERROR (Status) || (Http == NULL)) {
180 goto ON_ERROR;
181 }
182
183 //
184 // Init the configuration data and configure the HTTP child.
185 //
186 HttpIo->Image = Image;
187 HttpIo->Controller = Controller;
188 HttpIo->IpVersion = IpVersion;
189 HttpIo->Http = Http;
190 HttpIo->Callback = Callback;
191 HttpIo->Context = Context;
192 HttpIo->Timeout = PcdGet32 (PcdHttpIoTimeout);
193
194 if (ConfigData != NULL) {
195 if (HttpIo->IpVersion == IP_VERSION_4) {
196 HttpConfigData.LocalAddressIsIPv6 = FALSE;
197 HttpConfigData.HttpVersion = ConfigData->Config4.HttpVersion;
198 HttpConfigData.TimeOutMillisec = ConfigData->Config4.RequestTimeOut;
199
200 Http4AccessPoint.UseDefaultAddress = ConfigData->Config4.UseDefaultAddress;
201 Http4AccessPoint.LocalPort = ConfigData->Config4.LocalPort;
202 IP4_COPY_ADDRESS (&Http4AccessPoint.LocalAddress, &ConfigData->Config4.LocalIp);
203 IP4_COPY_ADDRESS (&Http4AccessPoint.LocalSubnet, &ConfigData->Config4.SubnetMask);
204 HttpConfigData.AccessPoint.IPv4Node = &Http4AccessPoint;
205 } else {
206 HttpConfigData.LocalAddressIsIPv6 = TRUE;
207 HttpConfigData.HttpVersion = ConfigData->Config6.HttpVersion;
208 HttpConfigData.TimeOutMillisec = ConfigData->Config6.RequestTimeOut;
209
210 Http6AccessPoint.LocalPort = ConfigData->Config6.LocalPort;
211 IP6_COPY_ADDRESS (&Http6AccessPoint.LocalAddress, &ConfigData->Config6.LocalIp);
212 HttpConfigData.AccessPoint.IPv6Node = &Http6AccessPoint;
213 }
214
215 Status = Http->Configure (Http, &HttpConfigData);
216 if (EFI_ERROR (Status)) {
217 goto ON_ERROR;
218 }
219 }
220
221 //
222 // Create events for variuos asynchronous operations.
223 //
224 Status = gBS->CreateEvent (
225 EVT_NOTIFY_SIGNAL,
226 TPL_NOTIFY,
228 &HttpIo->IsTxDone,
229 &Event
230 );
231 if (EFI_ERROR (Status)) {
232 goto ON_ERROR;
233 }
234
235 HttpIo->ReqToken.Event = Event;
236 HttpIo->ReqToken.Message = &HttpIo->ReqMessage;
237
238 Status = gBS->CreateEvent (
239 EVT_NOTIFY_SIGNAL,
240 TPL_NOTIFY,
242 &HttpIo->IsRxDone,
243 &Event
244 );
245 if (EFI_ERROR (Status)) {
246 goto ON_ERROR;
247 }
248
249 HttpIo->RspToken.Event = Event;
250 HttpIo->RspToken.Message = &HttpIo->RspMessage;
251
252 //
253 // Create TimeoutEvent for response
254 //
255 Status = gBS->CreateEvent (
256 EVT_TIMER,
257 TPL_CALLBACK,
258 NULL,
259 NULL,
260 &Event
261 );
262 if (EFI_ERROR (Status)) {
263 goto ON_ERROR;
264 }
265
266 HttpIo->TimeoutEvent = Event;
267 return EFI_SUCCESS;
268
269ON_ERROR:
270 HttpIoDestroyIo (HttpIo);
271
272 return Status;
273}
274
294 IN HTTP_IO *HttpIo,
295 IN EFI_HTTP_REQUEST_DATA *Request,
296 IN UINTN HeaderCount,
297 IN EFI_HTTP_HEADER *Headers,
298 IN UINTN BodyLength,
299 IN VOID *Body
300 )
301{
302 EFI_STATUS Status;
303 EFI_HTTP_PROTOCOL *Http;
304
305 if ((HttpIo == NULL) || (HttpIo->Http == NULL)) {
306 return EFI_INVALID_PARAMETER;
307 }
308
309 HttpIo->ReqToken.Status = EFI_NOT_READY;
310 HttpIo->ReqToken.Message->Data.Request = Request;
311 HttpIo->ReqToken.Message->HeaderCount = HeaderCount;
312 HttpIo->ReqToken.Message->Headers = Headers;
313 HttpIo->ReqToken.Message->BodyLength = BodyLength;
314 HttpIo->ReqToken.Message->Body = Body;
315
316 if (HttpIo->Callback != NULL) {
317 Status = HttpIo->Callback (
318 HttpIoRequest,
319 HttpIo->ReqToken.Message,
320 HttpIo->Context
321 );
322 if (EFI_ERROR (Status)) {
323 return Status;
324 }
325 }
326
327 //
328 // Queue the request token to HTTP instances.
329 //
330 Http = HttpIo->Http;
331 HttpIo->IsTxDone = FALSE;
332 Status = Http->Request (
333 Http,
334 &HttpIo->ReqToken
335 );
336 if (EFI_ERROR (Status)) {
337 return Status;
338 }
339
340 //
341 // Poll the network until transmit finish.
342 //
343 while (!HttpIo->IsTxDone) {
344 Http->Poll (Http);
345 }
346
347 return HttpIo->ReqToken.Status;
348}
349
367 IN HTTP_IO *HttpIo,
368 IN BOOLEAN RecvMsgHeader,
369 OUT HTTP_IO_RESPONSE_DATA *ResponseData
370 )
371{
372 EFI_STATUS Status;
373 EFI_HTTP_PROTOCOL *Http;
374
375 if ((HttpIo == NULL) || (HttpIo->Http == NULL) || (ResponseData == NULL)) {
376 return EFI_INVALID_PARAMETER;
377 }
378
379 //
380 // Queue the response token to HTTP instances.
381 //
382 HttpIo->RspToken.Status = EFI_NOT_READY;
383 if (RecvMsgHeader) {
384 HttpIo->RspToken.Message->Data.Response = &ResponseData->Response;
385 } else {
386 HttpIo->RspToken.Message->Data.Response = NULL;
387 }
388
389 HttpIo->RspToken.Message->HeaderCount = 0;
390 HttpIo->RspToken.Message->Headers = NULL;
391 HttpIo->RspToken.Message->BodyLength = ResponseData->BodyLength;
392 HttpIo->RspToken.Message->Body = ResponseData->Body;
393
394 Http = HttpIo->Http;
395 HttpIo->IsRxDone = FALSE;
396
397 //
398 // Start the timer, and wait Timeout seconds to receive the header packet.
399 //
400 Status = gBS->SetTimer (HttpIo->TimeoutEvent, TimerRelative, HttpIo->Timeout * TICKS_PER_MS);
401 if (EFI_ERROR (Status)) {
402 return Status;
403 }
404
405 Status = Http->Response (
406 Http,
407 &HttpIo->RspToken
408 );
409
410 if (EFI_ERROR (Status)) {
411 //
412 // Remove timeout timer from the event list.
413 //
414 gBS->SetTimer (HttpIo->TimeoutEvent, TimerCancel, 0);
415 return Status;
416 }
417
418 //
419 // Poll the network until receive finish.
420 //
421 while (!HttpIo->IsRxDone && EFI_ERROR (gBS->CheckEvent (HttpIo->TimeoutEvent))) {
422 Http->Poll (Http);
423 }
424
425 //
426 // Remove timeout timer from the event list.
427 //
428 gBS->SetTimer (HttpIo->TimeoutEvent, TimerCancel, 0);
429
430 if (!HttpIo->IsRxDone) {
431 //
432 // Timeout occurs, cancel the response token.
433 //
434 Http->Cancel (Http, &HttpIo->RspToken);
435
436 Status = EFI_TIMEOUT;
437
438 return Status;
439 } else {
440 HttpIo->IsRxDone = FALSE;
441 }
442
443 if ((HttpIo->Callback != NULL) &&
444 ((HttpIo->RspToken.Status == EFI_SUCCESS) || (HttpIo->RspToken.Status == EFI_HTTP_ERROR)))
445 {
446 Status = HttpIo->Callback (
447 HttpIoResponse,
448 HttpIo->RspToken.Message,
449 HttpIo->Context
450 );
451 if (EFI_ERROR (Status)) {
452 return Status;
453 }
454 }
455
456 //
457 // Store the received data into the wrapper.
458 //
459 ResponseData->Status = HttpIo->RspToken.Status;
460 ResponseData->HeaderCount = HttpIo->RspToken.Message->HeaderCount;
461 ResponseData->Headers = HttpIo->RspToken.Message->Headers;
462 ResponseData->BodyLength = HttpIo->RspToken.Message->BodyLength;
463
464 return Status;
465}
466
480 IN UINTN HeaderCount,
481 IN EFI_HTTP_HEADER *Headers,
482 OUT UINTN *ContentLength
483 )
484{
485 EFI_HTTP_HEADER *Header;
486
487 Header = HttpFindHeader (HeaderCount, Headers, HTTP_HEADER_CONTENT_LENGTH);
488 if (Header == NULL) {
489 return EFI_NOT_FOUND;
490 }
491
492 return AsciiStrDecimalToUintnS (Header->FieldValue, (CHAR8 **)NULL, ContentLength);
493}
494
508 IN HTTP_IO *HttpIo,
509 IN HTTP_IO_SEND_CHUNK_PROCESS *SendChunkProcess,
510 IN EFI_HTTP_MESSAGE *RequestMessage
511 )
512{
513 EFI_STATUS Status;
514 EFI_HTTP_HEADER *NewHeaders;
515 EFI_HTTP_HEADER *ContentLengthHeader;
516 UINTN AddNewHeader;
517 UINTN HeaderCount;
518 CHAR8 *MessageBody;
519 UINTN MessageBodyLength;
520 UINTN ChunkLength;
521 CHAR8 ChunkLengthStr[HTTP_IO_CHUNK_SIZE_STRING_LEN];
522 EFI_HTTP_REQUEST_DATA *SentRequestData;
523
524 AddNewHeader = 0;
525 NewHeaders = NULL;
526 MessageBody = NULL;
527 ContentLengthHeader = NULL;
528 MessageBodyLength = 0;
529
530 switch (*SendChunkProcess) {
531 case HttpIoSendChunkHeaderZeroContent:
532 ContentLengthHeader = HttpFindHeader (RequestMessage->HeaderCount, RequestMessage->Headers, HTTP_HEADER_CONTENT_LENGTH);
533 if (ContentLengthHeader == NULL) {
534 AddNewHeader = 1;
535 }
536
537 NewHeaders = AllocateZeroPool ((RequestMessage->HeaderCount + AddNewHeader) * sizeof (EFI_HTTP_HEADER));
538 CopyMem ((VOID *)NewHeaders, (VOID *)RequestMessage->Headers, RequestMessage->HeaderCount * sizeof (EFI_HTTP_HEADER));
539 if (AddNewHeader == 0) {
540 //
541 // Override content-length to Transfer-Encoding.
542 //
543 ContentLengthHeader = HttpFindHeader (RequestMessage->HeaderCount, NewHeaders, HTTP_HEADER_CONTENT_LENGTH);
544 ContentLengthHeader->FieldName = NULL;
545 ContentLengthHeader->FieldValue = NULL;
546 } else {
547 ContentLengthHeader = NewHeaders + RequestMessage->HeaderCount;
548 }
549
550 HttpSetFieldNameAndValue (ContentLengthHeader, HTTP_HEADER_TRANSFER_ENCODING, HTTP_HEADER_TRANSFER_ENCODING_CHUNKED);
551 HeaderCount = RequestMessage->HeaderCount + AddNewHeader;
552 MessageBodyLength = 0;
553 MessageBody = NULL;
554 SentRequestData = RequestMessage->Data.Request;
555 break;
556
557 case HttpIoSendChunkContent:
558 HeaderCount = 0;
559 NewHeaders = NULL;
560 SentRequestData = NULL;
561 if (RequestMessage->BodyLength > HTTP_IO_MAX_SEND_PAYLOAD) {
562 MessageBodyLength = HTTP_IO_MAX_SEND_PAYLOAD;
563 } else {
564 MessageBodyLength = RequestMessage->BodyLength;
565 }
566
568 ChunkLengthStr,
569 HTTP_IO_CHUNK_SIZE_STRING_LEN,
570 "%x%c%c",
571 MessageBodyLength,
572 CHUNKED_TRANSFER_CODING_CR,
573 CHUNKED_TRANSFER_CODING_LF
574 );
575 ChunkLength = AsciiStrLen (ChunkLengthStr);
576 MessageBody = AllocatePool (ChunkLength + MessageBodyLength + 2);
577 if (MessageBody == NULL) {
578 DEBUG ((DEBUG_ERROR, "Not enough memory for chunk transfer\n"));
579 return EFI_OUT_OF_RESOURCES;
580 }
581
582 //
583 // Build up the chunk transfer paylaod.
584 //
585 CopyMem (MessageBody, ChunkLengthStr, ChunkLength);
586 CopyMem (MessageBody + ChunkLength, RequestMessage->Body, MessageBodyLength);
587 *(MessageBody + ChunkLength + MessageBodyLength) = CHUNKED_TRANSFER_CODING_CR;
588 *(MessageBody + ChunkLength + MessageBodyLength + 1) = CHUNKED_TRANSFER_CODING_LF;
589 //
590 // Change variables for the next chunk trasnfer.
591 //
592 RequestMessage->BodyLength -= MessageBodyLength;
593 RequestMessage->Body = (VOID *)((CHAR8 *)RequestMessage->Body + MessageBodyLength);
594 MessageBodyLength += (ChunkLength + 2);
595 if (RequestMessage->BodyLength == 0) {
596 *SendChunkProcess = HttpIoSendChunkEndChunk;
597 }
598
599 break;
600
601 case HttpIoSendChunkEndChunk:
602 HeaderCount = 0;
603 NewHeaders = NULL;
604 SentRequestData = NULL;
606 ChunkLengthStr,
607 HTTP_IO_CHUNK_SIZE_STRING_LEN,
608 "0%c%c%c%c",
609 CHUNKED_TRANSFER_CODING_CR,
610 CHUNKED_TRANSFER_CODING_LF,
611 CHUNKED_TRANSFER_CODING_CR,
612 CHUNKED_TRANSFER_CODING_LF
613 );
614 MessageBody = AllocatePool (AsciiStrLen (ChunkLengthStr));
615 if (MessageBody == NULL) {
616 DEBUG ((DEBUG_ERROR, "Not enough memory for the end chunk transfer\n"));
617 return EFI_OUT_OF_RESOURCES;
618 }
619
620 CopyMem (MessageBody, ChunkLengthStr, AsciiStrLen (ChunkLengthStr));
621 MessageBodyLength = AsciiStrLen (ChunkLengthStr);
622 *SendChunkProcess = HttpIoSendChunkFinish;
623 break;
624
625 default:
626 return EFI_INVALID_PARAMETER;
627 }
628
629 Status = HttpIoSendRequest (
630 HttpIo,
631 SentRequestData,
632 HeaderCount,
633 NewHeaders,
634 MessageBodyLength,
635 MessageBody
636 );
637 if (ContentLengthHeader != NULL) {
638 if (ContentLengthHeader->FieldName != NULL) {
639 FreePool (ContentLengthHeader->FieldName);
640 }
641
642 if (ContentLengthHeader->FieldValue != NULL) {
643 FreePool (ContentLengthHeader->FieldValue);
644 }
645 }
646
647 if (NewHeaders != NULL) {
648 FreePool (NewHeaders);
649 }
650
651 if (MessageBody != NULL) {
652 FreePool (MessageBody);
653 }
654
655 return Status;
656}
657
679 IN HTTP_IO *HttpIo,
680 IN UINTN HeaderCount,
681 IN EFI_HTTP_HEADER *Headers,
682 OUT LIST_ENTRY **ChunkListHead,
683 OUT UINTN *ContentLength
684 )
685{
686 EFI_HTTP_HEADER *Header;
687 CHAR8 ChunkSizeAscii[256];
688 EFI_STATUS Status;
689 UINTN Index;
690 HTTP_IO_RESPONSE_DATA ResponseData;
691 UINTN TotalLength;
692 UINTN MaxTotalLength;
693 LIST_ENTRY *HttpChunks;
694 HTTP_IO_CHUNKS *ThisChunk;
695 LIST_ENTRY *ThisListEntry;
696
697 if ((ChunkListHead == NULL) || (ContentLength == NULL)) {
698 return EFI_INVALID_PARAMETER;
699 }
700
701 *ContentLength = 0;
702 Header = HttpFindHeader (HeaderCount, Headers, HTTP_HEADER_TRANSFER_ENCODING);
703 if (Header == NULL) {
704 return EFI_NOT_FOUND;
705 }
706
707 if (AsciiStrCmp (Header->FieldValue, HTTP_HEADER_TRANSFER_ENCODING_CHUNKED) != 0) {
708 return EFI_NOT_FOUND;
709 }
710
711 //
712 // Loop to get all chunks.
713 //
714 TotalLength = 0;
715 MaxTotalLength = PcdGet32 (PcdMaxHttpChunkTransfer);
716 HttpChunks = (LIST_ENTRY *)AllocateZeroPool (sizeof (LIST_ENTRY));
717 if (HttpChunks == NULL) {
718 Status = EFI_OUT_OF_RESOURCES;
719 goto ExitDeleteChunks;
720 }
721
722 InitializeListHead (HttpChunks);
723 DEBUG ((DEBUG_INFO, " Chunked transfer\n"));
724 while (TRUE) {
725 ZeroMem ((VOID *)&ResponseData, sizeof (HTTP_IO_RESPONSE_DATA));
726 ResponseData.BodyLength = HTTP_IO_CHUNKED_TRANSFER_CODING_DATA_LENGTH;
727 ResponseData.Body = ChunkSizeAscii;
728 Status = HttpIoRecvResponse (
729 HttpIo,
730 FALSE,
731 &ResponseData
732 );
733 if (EFI_ERROR (Status)) {
734 goto ExitDeleteChunks;
735 }
736
737 //
738 // Decoding Chunked Transfer Coding.
739 // Only decode chunk-size and last chunk.
740 //
741 DEBUG ((DEBUG_INFO, " Chunk HTTP Response StatusCode - %d\n", ResponseData.Response.StatusCode));
742 //
743 // Break if this is last chunk.
744 //
745 if (ChunkSizeAscii[0] == CHUNKED_TRANSFER_CODING_LAST_CHUNK) {
746 //
747 // Check if this is a valid Last-Chunk.
748 //
749 if ((ChunkSizeAscii[1] != CHUNKED_TRANSFER_CODING_CR) ||
750 (ChunkSizeAscii[2] != CHUNKED_TRANSFER_CODING_LF)
751 )
752 {
753 DEBUG ((DEBUG_ERROR, " This is an invalid Last-chunk\n"));
754 Status = EFI_INVALID_PARAMETER;
755 goto ExitDeleteChunks;
756 }
757
758 Status = EFI_SUCCESS;
759 DEBUG ((DEBUG_INFO, " Last-chunk\n"));
760 ThisChunk = (HTTP_IO_CHUNKS *)AllocateZeroPool (sizeof (HTTP_IO_CHUNKS));
761 if (ThisChunk == NULL) {
762 Status = EFI_OUT_OF_RESOURCES;
763 goto ExitDeleteChunks;
764 }
765
766 InitializeListHead (&ThisChunk->NextChunk);
767 ThisChunk->Length = ResponseData.BodyLength - 1 - 2; // Minus sizeof '0' and CRLF.
768 ThisChunk->Data = (CHAR8 *)AllocatePool (ThisChunk->Length);
769 if (ThisChunk->Data == NULL) {
770 FreePool ((UINT8 *)ThisChunk);
771 Status = EFI_OUT_OF_RESOURCES;
772 goto ExitDeleteChunks;
773 }
774
775 CopyMem ((UINT8 *)ThisChunk->Data, (UINT8 *)ResponseData.Body + 1, ThisChunk->Length);
776 TotalLength += ThisChunk->Length;
777 InsertTailList (HttpChunks, &ThisChunk->NextChunk);
778 break;
779 }
780
781 //
782 // Get the chunk length
783 //
784 Index = 0;
785 while ((ChunkSizeAscii[Index] != CHUNKED_TRANSFER_CODING_EXTENSION_SEPARATOR) &&
786 (ChunkSizeAscii[Index] != (CHAR8)CHUNKED_TRANSFER_CODING_CR) &&
787 (Index != HTTP_IO_CHUNKED_TRANSFER_CODING_DATA_LENGTH))
788 {
789 Index++;
790 }
791
792 if (Index == HTTP_IO_CHUNKED_TRANSFER_CODING_DATA_LENGTH) {
793 Status = EFI_NOT_FOUND;
794 goto ExitDeleteChunks;
795 }
796
797 ChunkSizeAscii[Index] = 0;
798 AsciiStrHexToUintnS (ChunkSizeAscii, NULL, ContentLength);
799 DEBUG ((DEBUG_INFO, " Length of this chunk %d\n", *ContentLength));
800 //
801 // Receive the data;
802 //
803 ThisChunk = (HTTP_IO_CHUNKS *)AllocateZeroPool (sizeof (HTTP_IO_CHUNKS));
804 if (ThisChunk == NULL) {
805 Status = EFI_OUT_OF_RESOURCES;
806 goto ExitDeleteChunks;
807 }
808
809 ResponseData.BodyLength = *ContentLength;
810 ResponseData.Body = (CHAR8 *)AllocatePool (*ContentLength);
811 if (ResponseData.Body == NULL) {
812 FreePool (ThisChunk);
813 Status = EFI_OUT_OF_RESOURCES;
814 goto ExitDeleteChunks;
815 }
816
817 InitializeListHead (&ThisChunk->NextChunk);
818 ThisChunk->Length = *ContentLength;
819 ThisChunk->Data = ResponseData.Body;
820 InsertTailList (HttpChunks, &ThisChunk->NextChunk);
821 Status = HttpIoRecvResponse (
822 HttpIo,
823 FALSE,
824 &ResponseData
825 );
826 if (EFI_ERROR (Status)) {
827 goto ExitDeleteChunks;
828 }
829
830 //
831 // Read CRLF
832 //
833 ZeroMem ((VOID *)&ResponseData, sizeof (HTTP_IO_RESPONSE_DATA));
834 ResponseData.BodyLength = 2;
835 ResponseData.Body = ChunkSizeAscii;
836 Status = HttpIoRecvResponse (
837 HttpIo,
838 FALSE,
839 &ResponseData
840 );
841 if (EFI_ERROR (Status)) {
842 goto ExitDeleteChunks;
843 }
844
845 //
846 // Verify the end of chunk payload.
847 //
848 if ((ChunkSizeAscii[0] != CHUNKED_TRANSFER_CODING_CR) ||
849 (ChunkSizeAscii[1] != CHUNKED_TRANSFER_CODING_LF)
850 )
851 {
852 DEBUG ((DEBUG_ERROR, " This is an invalid End-of-chunk notation.\n"));
853 goto ExitDeleteChunks;
854 }
855
856 TotalLength += *ContentLength;
857 if (TotalLength > MaxTotalLength) {
858 DEBUG ((DEBUG_ERROR, " Total chunk transfer payload exceeds the size defined by PcdMaxHttpChunkTransfer.\n"));
859 goto ExitDeleteChunks;
860 }
861 }
862
863 *ContentLength = TotalLength;
864 *ChunkListHead = HttpChunks;
865 DEBUG ((DEBUG_INFO, " Total of lengh of chunks :%d\n", TotalLength));
866 return EFI_SUCCESS;
867
868ExitDeleteChunks:
869 if (HttpChunks != NULL) {
870 while (!IsListEmpty (HttpChunks)) {
871 ThisListEntry = GetFirstNode (HttpChunks);
872 RemoveEntryList (ThisListEntry);
873 ThisChunk = (HTTP_IO_CHUNKS *)ThisListEntry;
874 if (ThisChunk->Data != NULL) {
875 FreePool (ThisChunk->Data);
876 }
877
878 FreePool (ThisListEntry);
879 }
880
881 FreePool (HttpChunks);
882 }
883
884 return Status;
885}
UINT64 UINTN
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
UINTN EFIAPI AsciiStrLen(IN CONST CHAR8 *String)
Definition: String.c:641
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
INTN EFIAPI AsciiStrCmp(IN CONST CHAR8 *FirstString, IN CONST CHAR8 *SecondString)
Definition: String.c:716
RETURN_STATUS EFIAPI AsciiStrDecimalToUintnS(IN CONST CHAR8 *String, OUT CHAR8 **EndPointer OPTIONAL, OUT UINTN *Data)
Definition: SafeString.c:2179
RETURN_STATUS EFIAPI AsciiStrHexToUintnS(IN CONST CHAR8 *String, OUT CHAR8 **EndPointer OPTIONAL, OUT UINTN *Data)
Definition: SafeString.c:2399
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_STATUS EFIAPI QueueDpc(IN EFI_TPL DpcTpl, IN EFI_DPC_PROCEDURE DpcProcedure, IN VOID *DpcContext OPTIONAL)
Definition: DpcLib.c:62
EFI_STATUS HttpIoCreateIo(IN EFI_HANDLE Image, IN EFI_HANDLE Controller, IN UINT8 IpVersion, IN HTTP_IO_CONFIG_DATA *ConfigData OPTIONAL, IN HTTP_IO_CALLBACK Callback, IN VOID *Context, OUT HTTP_IO *HttpIo)
Definition: DxeHttpIoLib.c:130
VOID EFIAPI HttpIoNotifyDpc(IN VOID *Context)
Definition: DxeHttpIoLib.c:28
EFI_STATUS HttpIoGetContentLength(IN UINTN HeaderCount, IN EFI_HTTP_HEADER *Headers, OUT UINTN *ContentLength)
Definition: DxeHttpIoLib.c:479
EFI_STATUS HttpIoSendChunkedTransfer(IN HTTP_IO *HttpIo, IN HTTP_IO_SEND_CHUNK_PROCESS *SendChunkProcess, IN EFI_HTTP_MESSAGE *RequestMessage)
Definition: DxeHttpIoLib.c:507
EFI_STATUS HttpIoGetChunkedTransferContent(IN HTTP_IO *HttpIo, IN UINTN HeaderCount, IN EFI_HTTP_HEADER *Headers, OUT LIST_ENTRY **ChunkListHead, OUT UINTN *ContentLength)
Definition: DxeHttpIoLib.c:678
VOID HttpIoDestroyIo(IN HTTP_IO *HttpIo)
Definition: DxeHttpIoLib.c:62
EFI_STATUS HttpIoSendRequest(IN HTTP_IO *HttpIo, IN EFI_HTTP_REQUEST_DATA *Request, IN UINTN HeaderCount, IN EFI_HTTP_HEADER *Headers, IN UINTN BodyLength, IN VOID *Body)
Definition: DxeHttpIoLib.c:293
VOID EFIAPI HttpIoNotify(IN EFI_EVENT Event, IN VOID *Context)
Definition: DxeHttpIoLib.c:44
EFI_STATUS HttpIoRecvResponse(IN HTTP_IO *HttpIo, IN BOOLEAN RecvMsgHeader, OUT HTTP_IO_RESPONSE_DATA *ResponseData)
Definition: DxeHttpIoLib.c:366
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define HTTP_HEADER_CONTENT_LENGTH
Definition: Http11.h:135
#define HTTP_HEADER_TRANSFER_ENCODING
Definition: Http11.h:144
EFI_STATUS(EFIAPI * HTTP_IO_CALLBACK)(IN HTTP_IO_CALLBACK_EVENT EventType, IN EFI_HTTP_MESSAGE *Message, IN VOID *Context)
Definition: HttpIoLib.h:42
HTTP_IO_SEND_CHUNK_PROCESS
Definition: HttpIoLib.h:121
EFI_STATUS EFIAPI HttpSetFieldNameAndValue(IN OUT EFI_HTTP_HEADER *HttpHeader, IN CONST CHAR8 *FieldName, IN CONST CHAR8 *FieldValue)
Definition: DxeHttpLib.c:1529
EFI_HTTP_HEADER *EFIAPI HttpFindHeader(IN UINTN HeaderCount, IN EFI_HTTP_HEADER *Headers, IN CHAR8 *FieldName)
Definition: DxeHttpLib.c:855
UINTN EFIAPI AsciiSPrint(OUT CHAR8 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR8 *FormatString,...)
Definition: PrintLib.c:813
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
EFI_STATUS EFIAPI NetLibCreateServiceChild(IN EFI_HANDLE Controller, IN EFI_HANDLE Image, IN EFI_GUID *ServiceBindingGuid, IN OUT EFI_HANDLE *ChildHandle)
Definition: DxeNetLib.c:1967
EFI_STATUS EFIAPI NetLibDestroyServiceChild(IN EFI_HANDLE Controller, IN EFI_HANDLE Image, IN EFI_GUID *ServiceBindingGuid, IN EFI_HANDLE ChildHandle)
Definition: DxeNetLib.c:2020
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
@ TimerCancel
Definition: UefiSpec.h:531
@ TimerRelative
Definition: UefiSpec.h:539
EFI_HTTP_VERSION HttpVersion
Definition: Http.h:154
EFI_HTTPv6_ACCESS_POINT * IPv6Node
Definition: Http.h:176
EFI_HTTPv4_ACCESS_POINT * IPv4Node
Definition: Http.h:171
BOOLEAN LocalAddressIsIPv6
Definition: Http.h:164
UINT32 TimeOutMillisec
Definition: Http.h:158
CHAR8 * FieldValue
Definition: Http.h:220
CHAR8 * FieldName
Definition: Http.h:215
EFI_IPv4_ADDRESS LocalSubnet
Definition: Http.h:124
EFI_IPv4_ADDRESS LocalAddress
Definition: Http.h:119
BOOLEAN UseDefaultAddress
Definition: Http.h:114
EFI_IPv6_ADDRESS LocalAddress
Definition: Http.h:139