32 *((BOOLEAN *)Context) =
TRUE;
73 Event = HttpIo->ReqToken.Event;
75 gBS->CloseEvent (Event);
78 Event = HttpIo->RspToken.Event;
80 gBS->CloseEvent (Event);
83 Event = HttpIo->TimeoutEvent;
85 gBS->CloseEvent (Event);
90 Http->Configure (Http,
NULL);
93 &gEfiHttpProtocolGuid,
102 &gEfiHttpServiceBindingProtocolGuid,
147 if ((Image ==
NULL) || (Controller ==
NULL) || (HttpIo ==
NULL)) {
148 return EFI_INVALID_PARAMETER;
151 if ((IpVersion != IP_VERSION_4) && (IpVersion != IP_VERSION_6)) {
152 return EFI_UNSUPPORTED;
164 &gEfiHttpServiceBindingProtocolGuid,
167 if (EFI_ERROR (Status)) {
171 Status =
gBS->OpenProtocol (
173 &gEfiHttpProtocolGuid,
177 EFI_OPEN_PROTOCOL_BY_DRIVER
179 if (EFI_ERROR (Status) || (Http ==
NULL)) {
186 HttpIo->Image = Image;
187 HttpIo->Controller = Controller;
188 HttpIo->IpVersion = IpVersion;
190 HttpIo->Callback = Callback;
191 HttpIo->Context = Context;
192 HttpIo->Timeout =
PcdGet32 (PcdHttpIoTimeout);
194 if (ConfigData !=
NULL) {
195 if (HttpIo->IpVersion == IP_VERSION_4) {
197 HttpConfigData.
HttpVersion = ConfigData->Config4.HttpVersion;
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;
207 HttpConfigData.
HttpVersion = ConfigData->Config6.HttpVersion;
210 Http6AccessPoint.
LocalPort = ConfigData->Config6.LocalPort;
211 IP6_COPY_ADDRESS (&Http6AccessPoint.
LocalAddress, &ConfigData->Config6.LocalIp);
212 HttpConfigData.AccessPoint.
IPv6Node = &Http6AccessPoint;
215 Status = Http->Configure (Http, &HttpConfigData);
216 if (EFI_ERROR (Status)) {
224 Status =
gBS->CreateEvent (
231 if (EFI_ERROR (Status)) {
235 HttpIo->ReqToken.Event = Event;
236 HttpIo->ReqToken.Message = &HttpIo->ReqMessage;
238 Status =
gBS->CreateEvent (
245 if (EFI_ERROR (Status)) {
249 HttpIo->RspToken.Event = Event;
250 HttpIo->RspToken.Message = &HttpIo->RspMessage;
255 Status =
gBS->CreateEvent (
262 if (EFI_ERROR (Status)) {
266 HttpIo->TimeoutEvent = Event;
305 if ((HttpIo ==
NULL) || (HttpIo->Http ==
NULL)) {
306 return EFI_INVALID_PARAMETER;
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;
316 if (HttpIo->Callback !=
NULL) {
317 Status = HttpIo->Callback (
319 HttpIo->ReqToken.Message,
322 if (EFI_ERROR (Status)) {
331 HttpIo->IsTxDone =
FALSE;
332 Status = Http->Request (
336 if (EFI_ERROR (Status)) {
343 while (!HttpIo->IsTxDone) {
347 return HttpIo->ReqToken.Status;
368 IN BOOLEAN RecvMsgHeader,
375 if ((HttpIo ==
NULL) || (HttpIo->Http ==
NULL) || (ResponseData ==
NULL)) {
376 return EFI_INVALID_PARAMETER;
382 HttpIo->RspToken.Status = EFI_NOT_READY;
384 HttpIo->RspToken.Message->Data.Response = &ResponseData->Response;
386 HttpIo->RspToken.Message->Data.Response =
NULL;
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;
395 HttpIo->IsRxDone =
FALSE;
400 Status =
gBS->SetTimer (HttpIo->TimeoutEvent,
TimerRelative, HttpIo->Timeout * TICKS_PER_MS);
401 if (EFI_ERROR (Status)) {
405 Status = Http->Response (
410 if (EFI_ERROR (Status)) {
421 while (!HttpIo->IsRxDone && EFI_ERROR (
gBS->CheckEvent (HttpIo->TimeoutEvent))) {
430 if (!HttpIo->IsRxDone) {
434 Http->Cancel (Http, &HttpIo->RspToken);
436 Status = EFI_TIMEOUT;
440 HttpIo->IsRxDone =
FALSE;
443 if ((HttpIo->Callback !=
NULL) &&
444 ((HttpIo->RspToken.Status ==
EFI_SUCCESS) || (HttpIo->RspToken.Status == EFI_HTTP_ERROR)))
446 Status = HttpIo->Callback (
448 HttpIo->RspToken.Message,
451 if (EFI_ERROR (Status)) {
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;
488 if (Header ==
NULL) {
489 return EFI_NOT_FOUND;
519 UINTN MessageBodyLength;
521 CHAR8 ChunkLengthStr[HTTP_IO_CHUNK_SIZE_STRING_LEN];
527 ContentLengthHeader =
NULL;
528 MessageBodyLength = 0;
530 switch (*SendChunkProcess) {
531 case HttpIoSendChunkHeaderZeroContent:
533 if (ContentLengthHeader ==
NULL) {
538 CopyMem ((VOID *)NewHeaders, (VOID *)RequestMessage->Headers, RequestMessage->HeaderCount * sizeof (
EFI_HTTP_HEADER));
539 if (AddNewHeader == 0) {
547 ContentLengthHeader = NewHeaders + RequestMessage->HeaderCount;
551 HeaderCount = RequestMessage->HeaderCount + AddNewHeader;
552 MessageBodyLength = 0;
554 SentRequestData = RequestMessage->Data.Request;
557 case HttpIoSendChunkContent:
560 SentRequestData =
NULL;
561 if (RequestMessage->BodyLength > HTTP_IO_MAX_SEND_PAYLOAD) {
562 MessageBodyLength = HTTP_IO_MAX_SEND_PAYLOAD;
564 MessageBodyLength = RequestMessage->BodyLength;
569 HTTP_IO_CHUNK_SIZE_STRING_LEN,
572 CHUNKED_TRANSFER_CODING_CR,
573 CHUNKED_TRANSFER_CODING_LF
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;
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;
592 RequestMessage->BodyLength -= MessageBodyLength;
593 RequestMessage->Body = (VOID *)((CHAR8 *)RequestMessage->Body + MessageBodyLength);
594 MessageBodyLength += (ChunkLength + 2);
595 if (RequestMessage->BodyLength == 0) {
596 *SendChunkProcess = HttpIoSendChunkEndChunk;
601 case HttpIoSendChunkEndChunk:
604 SentRequestData =
NULL;
607 HTTP_IO_CHUNK_SIZE_STRING_LEN,
609 CHUNKED_TRANSFER_CODING_CR,
610 CHUNKED_TRANSFER_CODING_LF,
611 CHUNKED_TRANSFER_CODING_CR,
612 CHUNKED_TRANSFER_CODING_LF
615 if (MessageBody ==
NULL) {
616 DEBUG ((DEBUG_ERROR,
"Not enough memory for the end chunk transfer\n"));
617 return EFI_OUT_OF_RESOURCES;
622 *SendChunkProcess = HttpIoSendChunkFinish;
626 return EFI_INVALID_PARAMETER;
637 if (ContentLengthHeader !=
NULL) {
647 if (NewHeaders !=
NULL) {
651 if (MessageBody !=
NULL) {
687 CHAR8 ChunkSizeAscii[256];
692 UINTN MaxTotalLength;
697 if ((ChunkListHead ==
NULL) || (ContentLength ==
NULL)) {
698 return EFI_INVALID_PARAMETER;
703 if (Header ==
NULL) {
704 return EFI_NOT_FOUND;
707 if (
AsciiStrCmp (Header->FieldValue, HTTP_HEADER_TRANSFER_ENCODING_CHUNKED) != 0) {
708 return EFI_NOT_FOUND;
715 MaxTotalLength =
PcdGet32 (PcdMaxHttpChunkTransfer);
717 if (HttpChunks ==
NULL) {
718 Status = EFI_OUT_OF_RESOURCES;
719 goto ExitDeleteChunks;
723 DEBUG ((DEBUG_INFO,
" Chunked transfer\n"));
726 ResponseData.BodyLength = HTTP_IO_CHUNKED_TRANSFER_CODING_DATA_LENGTH;
727 ResponseData.Body = ChunkSizeAscii;
733 if (EFI_ERROR (Status)) {
734 goto ExitDeleteChunks;
741 DEBUG ((DEBUG_INFO,
" Chunk HTTP Response StatusCode - %d\n", ResponseData.Response.StatusCode));
745 if (ChunkSizeAscii[0] == CHUNKED_TRANSFER_CODING_LAST_CHUNK) {
749 if ((ChunkSizeAscii[1] != CHUNKED_TRANSFER_CODING_CR) ||
750 (ChunkSizeAscii[2] != CHUNKED_TRANSFER_CODING_LF)
753 DEBUG ((DEBUG_ERROR,
" This is an invalid Last-chunk\n"));
754 Status = EFI_INVALID_PARAMETER;
755 goto ExitDeleteChunks;
759 DEBUG ((DEBUG_INFO,
" Last-chunk\n"));
761 if (ThisChunk ==
NULL) {
762 Status = EFI_OUT_OF_RESOURCES;
763 goto ExitDeleteChunks;
767 ThisChunk->Length = ResponseData.BodyLength - 1 - 2;
768 ThisChunk->Data = (CHAR8 *)
AllocatePool (ThisChunk->Length);
769 if (ThisChunk->Data ==
NULL) {
771 Status = EFI_OUT_OF_RESOURCES;
772 goto ExitDeleteChunks;
775 CopyMem ((UINT8 *)ThisChunk->Data, (UINT8 *)ResponseData.Body + 1, ThisChunk->Length);
776 TotalLength += ThisChunk->Length;
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))
792 if (Index == HTTP_IO_CHUNKED_TRANSFER_CODING_DATA_LENGTH) {
793 Status = EFI_NOT_FOUND;
794 goto ExitDeleteChunks;
797 ChunkSizeAscii[Index] = 0;
799 DEBUG ((DEBUG_INFO,
" Length of this chunk %d\n", *ContentLength));
804 if (ThisChunk ==
NULL) {
805 Status = EFI_OUT_OF_RESOURCES;
806 goto ExitDeleteChunks;
809 ResponseData.BodyLength = *ContentLength;
810 ResponseData.Body = (CHAR8 *)
AllocatePool (*ContentLength);
811 if (ResponseData.Body ==
NULL) {
813 Status = EFI_OUT_OF_RESOURCES;
814 goto ExitDeleteChunks;
818 ThisChunk->Length = *ContentLength;
819 ThisChunk->Data = ResponseData.Body;
826 if (EFI_ERROR (Status)) {
827 goto ExitDeleteChunks;
834 ResponseData.BodyLength = 2;
835 ResponseData.Body = ChunkSizeAscii;
841 if (EFI_ERROR (Status)) {
842 goto ExitDeleteChunks;
848 if ((ChunkSizeAscii[0] != CHUNKED_TRANSFER_CODING_CR) ||
849 (ChunkSizeAscii[1] != CHUNKED_TRANSFER_CODING_LF)
852 DEBUG ((DEBUG_ERROR,
" This is an invalid End-of-chunk notation.\n"));
853 goto ExitDeleteChunks;
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;
863 *ContentLength = TotalLength;
864 *ChunkListHead = HttpChunks;
865 DEBUG ((DEBUG_INFO,
" Total of lengh of chunks :%d\n", TotalLength));
869 if (HttpChunks !=
NULL) {
874 if (ThisChunk->Data !=
NULL) {
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
UINTN EFIAPI AsciiStrLen(IN CONST CHAR8 *String)
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
INTN EFIAPI AsciiStrCmp(IN CONST CHAR8 *FirstString, IN CONST CHAR8 *SecondString)
RETURN_STATUS EFIAPI AsciiStrDecimalToUintnS(IN CONST CHAR8 *String, OUT CHAR8 **EndPointer OPTIONAL, OUT UINTN *Data)
RETURN_STATUS EFIAPI AsciiStrHexToUintnS(IN CONST CHAR8 *String, OUT CHAR8 **EndPointer OPTIONAL, OUT UINTN *Data)
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
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)
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)
VOID EFIAPI HttpIoNotifyDpc(IN VOID *Context)
EFI_STATUS HttpIoGetContentLength(IN UINTN HeaderCount, IN EFI_HTTP_HEADER *Headers, OUT UINTN *ContentLength)
EFI_STATUS HttpIoSendChunkedTransfer(IN HTTP_IO *HttpIo, IN HTTP_IO_SEND_CHUNK_PROCESS *SendChunkProcess, IN EFI_HTTP_MESSAGE *RequestMessage)
EFI_STATUS HttpIoGetChunkedTransferContent(IN HTTP_IO *HttpIo, IN UINTN HeaderCount, IN EFI_HTTP_HEADER *Headers, OUT LIST_ENTRY **ChunkListHead, OUT UINTN *ContentLength)
VOID HttpIoDestroyIo(IN HTTP_IO *HttpIo)
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)
VOID EFIAPI HttpIoNotify(IN EFI_EVENT Event, IN VOID *Context)
EFI_STATUS HttpIoRecvResponse(IN HTTP_IO *HttpIo, IN BOOLEAN RecvMsgHeader, OUT HTTP_IO_RESPONSE_DATA *ResponseData)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define HTTP_HEADER_CONTENT_LENGTH
#define HTTP_HEADER_TRANSFER_ENCODING
EFI_STATUS(EFIAPI * HTTP_IO_CALLBACK)(IN HTTP_IO_CALLBACK_EVENT EventType, IN EFI_HTTP_MESSAGE *Message, IN VOID *Context)
HTTP_IO_SEND_CHUNK_PROCESS
EFI_STATUS EFIAPI HttpSetFieldNameAndValue(IN OUT EFI_HTTP_HEADER *HttpHeader, IN CONST CHAR8 *FieldName, IN CONST CHAR8 *FieldValue)
EFI_HTTP_HEADER *EFIAPI HttpFindHeader(IN UINTN HeaderCount, IN EFI_HTTP_HEADER *Headers, IN CHAR8 *FieldName)
UINTN EFIAPI AsciiSPrint(OUT CHAR8 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR8 *FormatString,...)
#define DEBUG(Expression)
EFI_STATUS EFIAPI NetLibCreateServiceChild(IN EFI_HANDLE Controller, IN EFI_HANDLE Image, IN EFI_GUID *ServiceBindingGuid, IN OUT EFI_HANDLE *ChildHandle)
EFI_STATUS EFIAPI NetLibDestroyServiceChild(IN EFI_HANDLE Controller, IN EFI_HANDLE Image, IN EFI_GUID *ServiceBindingGuid, IN EFI_HANDLE ChildHandle)
#define PcdGet32(TokenName)
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
EFI_HTTP_VERSION HttpVersion
EFI_HTTPv6_ACCESS_POINT * IPv6Node
EFI_HTTPv4_ACCESS_POINT * IPv4Node
BOOLEAN LocalAddressIsIPv6
EFI_IPv4_ADDRESS LocalSubnet
EFI_IPv4_ADDRESS LocalAddress
BOOLEAN UseDefaultAddress
EFI_IPv6_ADDRESS LocalAddress