From: "Maciej Rabeda" <maciej.rabeda@linux.intel.com>
To: Abner Chang <abner.chang@hpe.com>, devel@edk2.groups.io
Cc: Jiaxin Wu <jiaxin.wu@intel.com>, Siyuan Fu <siyuan.fu@intel.com>,
Nickle Wang <nickle.wang@hpe.com>
Subject: Re: [DxeHttpIoLib PATCH V3 1/3] NetworkPkg/Library: Implementation of Http IO Helper Library
Date: Wed, 28 Oct 2020 19:57:46 +0100 [thread overview]
Message-ID: <6a4f6c0f-dadc-8aef-c56e-cb946b0640ca@linux.intel.com> (raw)
In-Reply-To: <20201026060537.31852-2-abner.chang@hpe.com>
Hi Abner,
Review done - comments inline. Sorry to be picky at times, but we all
want quality code in our UEFI FWs :)
Thanks,
Maciej
On 26-Oct-20 07:05, Abner Chang wrote:
> Add HTTP IO helper library which could be used by HTTP applications
> such as HTTP Boot, Redfish HTTP REST EX driver instance and etc.
>
> Signed-off-by: Abner Chang <abner.chang@hpe.com>
>
> Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
> Cc: Jiaxin Wu <jiaxin.wu@intel.com>
> Cc: Siyuan Fu <siyuan.fu@intel.com>
> Cc: Nickle Wang <nickle.wang@hpe.com>
> ---
> NetworkPkg/Include/Library/HttpIoLib.h | 328 +++++++
> .../Library/DxeHttpIoLib/DxeHttpIoLib.c | 823 ++++++++++++++++++
> .../Library/DxeHttpIoLib/DxeHttpIoLib.inf | 43 +
> .../Library/DxeHttpIoLib/DxeHttpIoLib.uni | 13 +
> 4 files changed, 1207 insertions(+)
> create mode 100644 NetworkPkg/Include/Library/HttpIoLib.h
> create mode 100644 NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.c
> create mode 100644 NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.inf
> create mode 100644 NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.uni
>
> diff --git a/NetworkPkg/Include/Library/HttpIoLib.h b/NetworkPkg/Include/Library/HttpIoLib.h
> new file mode 100644
> index 0000000000..8f3804ca42
> --- /dev/null
> +++ b/NetworkPkg/Include/Library/HttpIoLib.h
> @@ -0,0 +1,328 @@
> +/** @file
> + HttpIoLib.h.
> +
> +(C) Copyright 2020 Hewlett-Packard Development Company, L.P.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef HTTP_IO_LIB_H_
> +#define HTTP_IO_LIB_H_
> +
> +#include <IndustryStandard/Http11.h>
> +
> +#include <Library/DpcLib.h>
> +#include <Library/HttpLib.h>
> +#include <Library/NetLib.h>
> +
> +#define HTTP_IO_MAX_SEND_PAYLOAD 1024
> +#define HTTP_IO_CHUNK_SIZE_STRING_LEN 50
> +#define HTTP_IO_CHUNKED_TRANSFER_CODING_DATA_LENGTH 256
> +
> +///
> +/// HTTP_IO_CALLBACK_EVENT
> +///
> +typedef enum {
> + HttpIoRequest,
> + HttpIoResponse
> +} HTTP_IO_CALLBACK_EVENT;
> +
> +/**
> + HttpIo Callback function which will be invoked when specified HTTP_IO_CALLBACK_EVENT happened.
> +
> + @param[in] EventType Indicate the Event type that occurs in the current callback.
> + @param[in] Message HTTP message which will be send to, or just received from HTTP server.
> + @param[in] Context The Callback Context pointer.
> +
> + @retval EFI_SUCCESS Tells the HttpIo to continue the HTTP process.
> + @retval Others Tells the HttpIo to abort the current HTTP process.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI * HTTP_IO_CALLBACK) (
> + IN HTTP_IO_CALLBACK_EVENT EventType,
> + IN EFI_HTTP_MESSAGE *Message,
> + IN VOID *Context
> + );
> +
> +///
> +/// A wrapper structure to hold the received HTTP response data.
> +///
> +typedef struct {
> + EFI_HTTP_RESPONSE_DATA Response;
> + UINTN HeaderCount;
> + EFI_HTTP_HEADER *Headers;
> + UINTN BodyLength;
> + CHAR8 *Body;
> + EFI_STATUS Status;
> +} HTTP_IO_RESPONSE_DATA;
> +
> +///
> +/// HTTP_IO configuration data for IPv4
> +///
> +typedef struct {
> + EFI_HTTP_VERSION HttpVersion;
> + UINT32 RequestTimeOut; ///< In milliseconds.
> + UINT32 ResponseTimeOut; ///< In milliseconds.
> + BOOLEAN UseDefaultAddress;
> + EFI_IPv4_ADDRESS LocalIp;
> + EFI_IPv4_ADDRESS SubnetMask;
> + UINT16 LocalPort;
> +} HTTP4_IO_CONFIG_DATA;
> +
> +///
> +/// HTTP_IO configuration data for IPv6
> +///
> +typedef struct {
> + EFI_HTTP_VERSION HttpVersion;
> + UINT32 RequestTimeOut; ///< In milliseconds.
> + BOOLEAN UseDefaultAddress;
> + EFI_IPv6_ADDRESS LocalIp;
> + UINT16 LocalPort;
> +} HTTP6_IO_CONFIG_DATA;
> +
> +///
> +/// HTTP_IO configuration
> +///
> +typedef union {
> + HTTP4_IO_CONFIG_DATA Config4;
> + HTTP6_IO_CONFIG_DATA Config6;
> +} HTTP_IO_CONFIG_DATA;
> +
> +///
> +/// HTTP_IO wrapper of the EFI HTTP service.
> +///
> +typedef struct {
> + UINT8 IpVersion;
> + EFI_HANDLE Image;
> + EFI_HANDLE Controller;
> + EFI_HANDLE Handle;
> +
> + EFI_HTTP_PROTOCOL *Http;
> +
> + HTTP_IO_CALLBACK Callback;
> + VOID *Context;
> +
> + EFI_HTTP_TOKEN ReqToken;
> + EFI_HTTP_MESSAGE ReqMessage;
> + EFI_HTTP_TOKEN RspToken;
> + EFI_HTTP_MESSAGE RspMessage;
> +
> + BOOLEAN IsTxDone;
> + BOOLEAN IsRxDone;
> +
> + EFI_EVENT TimeoutEvent;
> + UINT32 Timeout;
> +} HTTP_IO;
> +
> +///
> +/// Process code of HTTP chunk transfer.
> +///
> +typedef enum {
> + HttpIoSendChunkNone = 0,
> + HttpIoSendChunkHeaderZeroContent,
> + HttpIoSendChunkContent,
> + HttpIoSendChunkEndChunk,
> + HttpIoSendChunkFinish
> +} HTTP_IO_SEND_CHUNK_PROCESS;
> +
> +///
> +/// Process code of HTTP non chunk transfer.
> +///
> +typedef enum {
> + HttpIoSendNonChunkNone = 0,
> + HttpIoSendNonChunkHeaderZeroContent,
> + HttpIoSendNonChunkContent,
> + HttpIoSendNonChunkFinish
> +} HTTP_IO_SEND_NON_CHUNK_PROCESS;
> +
> +///
> +/// Chunk links for HTTP chunked transfer coding.
> +///
> +typedef struct {
> + LIST_ENTRY NextChunk;
> + UINTN Length;
> + CHAR8 *Data;
> +} HTTP_IO_CHUNKS;
> +
> +/**
> + Notify the callback function when an event is triggered.
> +
> + @param[in] Context The opaque parameter to the function.
> +
> +**/
> +VOID
> +EFIAPI
> +HttpIoNotifyDpc (
> + IN VOID *Context
> + );
> +
> +/**
> + Request HttpIoNotifyDpc as a DPC at TPL_CALLBACK.
> +
> + @param[in] Event The event signaled.
> + @param[in] Context The opaque parameter to the function.
> +
> +**/
> +VOID
> +EFIAPI
> +HttpIoNotify (
> + IN EFI_EVENT Event,
> + IN VOID *Context
> + );
> +
> +/**
> + Destroy the HTTP_IO and release the resources.
> +
> + @param[in] HttpIo The HTTP_IO which wraps the HTTP service to be destroyed.
> +
> +**/
> +VOID
> +HttpIoDestroyIo (
> + IN HTTP_IO *HttpIo
> + );
> +
> +/**
> + Create a HTTP_IO to access the HTTP service. It will create and configure
> + a HTTP child handle.
> +
> + @param[in] Image The handle of the driver image.
> + @param[in] Controller The handle of the controller.
> + @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
> + @param[in] ConfigData The HTTP_IO configuration data.
> + @param[in] Callback Callback function which will be invoked when specified
> + HTTP_IO_CALLBACK_EVENT happened.
> + @param[in] Context The Context data which will be passed to the Callback function.
> + @param[out] HttpIo The HTTP_IO.
> +
> + @retval EFI_SUCCESS The HTTP_IO is created and configured.
> + @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
> + @retval EFI_UNSUPPORTED One or more of the control options are not
> + supported in the implementation.
> + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
> + @retval Others Failed to create the HTTP_IO or configure it.
> +
> +**/
> +EFI_STATUS
> +HttpIoCreateIo (
> + IN EFI_HANDLE Image,
> + IN EFI_HANDLE Controller,
> + IN UINT8 IpVersion,
> + IN HTTP_IO_CONFIG_DATA *ConfigData,
> + IN HTTP_IO_CALLBACK Callback,
> + IN VOID *Context,
> + OUT HTTP_IO *HttpIo
> + );
> +
> +/**
> + Synchronously send a HTTP REQUEST message to the server.
> +
> + @param[in] HttpIo The HttpIo wrapping the HTTP service.
> + @param[in] Request A pointer to storage such data as URL and HTTP method.
> + @param[in] HeaderCount Number of HTTP header structures in Headers list.
> + @param[in] Headers Array containing list of HTTP headers.
> + @param[in] BodyLength Length in bytes of the HTTP body.
> + @param[in] Body Body associated with the HTTP request.
> +
> + @retval EFI_SUCCESS The HTTP request is transmitted.
> + @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
> + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
> + @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
> + @retval Others Other errors as indicated.
> +
> +**/
> +EFI_STATUS
> +HttpIoSendRequest (
> + IN HTTP_IO *HttpIo,
> + IN EFI_HTTP_REQUEST_DATA *Request, OPTIONAL
> + IN UINTN HeaderCount,
> + IN EFI_HTTP_HEADER *Headers, OPTIONAL
> + IN UINTN BodyLength,
> + IN VOID *Body OPTIONAL
> + );
> +
> +/**
> + Synchronously receive a HTTP RESPONSE message from the server.
> +
> + @param[in] HttpIo The HttpIo wrapping the HTTP service.
> + @param[in] RecvMsgHeader TRUE to receive a new HTTP response (from message header).
> + FALSE to continue receive the previous response message.
> + @param[out] ResponseData Point to a wrapper of the received response data.
> +
> + @retval EFI_SUCCESS The HTTP response is received.
> + @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
> + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
> + @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
> + @retval Others Other errors as indicated.
> +
> +**/
> +EFI_STATUS
> +HttpIoRecvResponse (
> + IN HTTP_IO *HttpIo,
> + IN BOOLEAN RecvMsgHeader,
> + OUT HTTP_IO_RESPONSE_DATA *ResponseData
> + );
> +
> +/**
> + Get the value of the content length if there is a "Content-Length" header.
> +
> + @param[in] HeaderCount Number of HTTP header structures in Headers.
> + @param[in] Headers Array containing list of HTTP headers.
> + @param[out] ContentLength Pointer to save the value of the content length.
> +
> + @retval EFI_SUCCESS Successfully get the content length.
> + @retval EFI_NOT_FOUND No "Content-Length" header in the Headers.
> +
> +**/
> +EFI_STATUS
> +HttpIoGetContentLength (
> + IN UINTN HeaderCount,
> + IN EFI_HTTP_HEADER *Headers,
> + OUT UINTN *ContentLength
> + );
> +
> +/**
> + Synchronously receive a HTTP RESPONSE message from the server.
> +
> + @param[in] HttpIo The HttpIo wrapping the HTTP service.
> + @param[in] HeaderCount Number of headers in Headers.
> + @param[in] Headers Array containing list of HTTP headers.
> + @param[out] ChunkListHead A pointer to receivce list head of chunked data.
> + Caller has to release memory of ChunkListHead
> + and all list entries.
> + @param[out] ContentLength Total content length
> +
> + @retval EFI_SUCCESS The HTTP chunked transfer is received.
> + @retval EFI_NOT_FOUND No chunked transfer coding header found.
> + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
> + @retval EFI_INVALID_PARAMETER Improper parameters.
> + @retval Others Other errors as indicated.
> +
> +**/
> +EFI_STATUS
> +HttpIoGetChunkedTransferContent (
> + IN HTTP_IO *HttpIo,
> + IN UINTN HeaderCount,
> + IN EFI_HTTP_HEADER *Headers,
> + OUT LIST_ENTRY **ChunkListHead,
> + OUT UINTN *ContentLength
> + );
> +
> +/**
> + Send HTTP request in chunks.
> +
> + @param[in] HttpIo The HttpIo wrapping the HTTP service.
> + @param[in] SendChunkProcess Pointer to current chunk process status.
> + @param[out] RequestMessage Request to send.
> +
> + @retval EFI_SUCCESS Successfully to send chunk data according to SendChunkProcess.
> + @retval Other Other errors.
> +
> +**/
> +EFI_STATUS
> +HttpIoSendChunkedTransfer (
> + IN HTTP_IO *HttpIo,
> + IN HTTP_IO_SEND_CHUNK_PROCESS *SendChunkProcess,
> + IN EFI_HTTP_MESSAGE *RequestMessage
> +);
> +#endif
> diff --git a/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.c b/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.c
> new file mode 100644
> index 0000000000..88d647e42d
> --- /dev/null
> +++ b/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.c
> @@ -0,0 +1,823 @@
> +/** @file
> + Http IO Helper Library.
> +
> + (C) Copyright 2020 Hewlett-Packard Development Company, L.P.<BR>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Uefi.h>
> +
> +#include <Protocol/Http.h>
> +
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/HttpIoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +/**
> + Notify the callback function when an event is triggered.
> +
> + @param[in] Context The opaque parameter to the function.
> +
> +**/
> +VOID
> +EFIAPI
> +HttpIoNotifyDpc (
> + IN VOID *Context
> + )
> +{
> + *((BOOLEAN *) Context) = TRUE;
> +}
> +
> +/**
> + Request HttpIoNotifyDpc as a DPC at TPL_CALLBACK.
> +
> + @param[in] Event The event signaled.
> + @param[in] Context The opaque parameter to the function.
> +
> +**/
> +VOID
> +EFIAPI
> +HttpIoNotify (
> + IN EFI_EVENT Event,
> + IN VOID *Context
> + )
> +{
> + //
> + // Request HttpIoNotifyDpc as a DPC at TPL_CALLBACK
> + //
> + QueueDpc (TPL_CALLBACK, HttpIoNotifyDpc, Context);
> +}
> +
> +/**
> + Destroy the HTTP_IO and release the resources.
> +
> + @param[in] HttpIo The HTTP_IO which wraps the HTTP service to be destroyed.
> +
> +**/
> +VOID
> +HttpIoDestroyIo (
> + IN HTTP_IO *HttpIo
> + )
> +{
> + EFI_HTTP_PROTOCOL *Http;
> + EFI_EVENT Event;
> +
> + if (HttpIo == NULL) {
> + return;
> + }
> +
> + Event = HttpIo->ReqToken.Event;
> + if (Event != NULL) {
> + gBS->CloseEvent (Event);
> + }
> +
> + Event = HttpIo->RspToken.Event;
> + if (Event != NULL) {
> + gBS->CloseEvent (Event);
> + }
> +
> + Event = HttpIo->TimeoutEvent;
> + if (Event != NULL) {
> + gBS->CloseEvent (Event);
> + }
> +
> + Http = HttpIo->Http;
> + if (Http != NULL) {
> + Http->Configure (Http, NULL);
> + gBS->CloseProtocol (
> + HttpIo->Handle,
> + &gEfiHttpProtocolGuid,
> + HttpIo->Image,
> + HttpIo->Controller
> + );
> + }
> +
> + NetLibDestroyServiceChild (
> + HttpIo->Controller,
> + HttpIo->Image,
> + &gEfiHttpServiceBindingProtocolGuid,
> + HttpIo->Handle
> + );
> +}
> +
> +/**
> + Create a HTTP_IO to access the HTTP service. It will create and configure
> + a HTTP child handle.
> +
> + @param[in] Image The handle of the driver image.
> + @param[in] Controller The handle of the controller.
> + @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
> + @param[in] ConfigData The HTTP_IO configuration data ,
> + NULL means not to configure the HTTP child.
> + @param[in] Callback Callback function which will be invoked when specified
> + HTTP_IO_CALLBACK_EVENT happened.
> + @param[in] Context The Context data which will be passed to the Callback function.
> + @param[out] HttpIo The HTTP_IO.
> +
> + @retval EFI_SUCCESS The HTTP_IO is created and configured.
> + @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
> + @retval EFI_UNSUPPORTED One or more of the control options are not
> + supported in the implementation.
> + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
> + @retval Others Failed to create the HTTP_IO or configure it.
> +
> +**/
> +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
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HTTP_CONFIG_DATA HttpConfigData;
> + EFI_HTTPv4_ACCESS_POINT Http4AccessPoint;
> + EFI_HTTPv6_ACCESS_POINT Http6AccessPoint;
> + EFI_HTTP_PROTOCOL *Http;
> + EFI_EVENT Event;
> +
> + if ((Image == NULL) || (Controller == NULL) || (HttpIo == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (IpVersion != IP_VERSION_4 && IpVersion != IP_VERSION_6) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + ZeroMem (HttpIo, sizeof (HTTP_IO));
> + ZeroMem (&HttpConfigData, sizeof (EFI_HTTP_CONFIG_DATA));
> +
> + //
> + // Create the HTTP child instance and get the HTTP protocol.
> + //
> + Status = NetLibCreateServiceChild (
> + Controller,
> + Image,
> + &gEfiHttpServiceBindingProtocolGuid,
> + &HttpIo->Handle
> + );
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = gBS->OpenProtocol (
> + HttpIo->Handle,
> + &gEfiHttpProtocolGuid,
> + (VOID **) &Http,
> + Image,
> + Controller,
> + EFI_OPEN_PROTOCOL_BY_DRIVER
> + );
> + if (EFI_ERROR (Status) || (Http == NULL)) {
> + goto ON_ERROR;
> + }
> +
> + //
> + // Init the configuration data and configure the HTTP child.
> + //
> + HttpIo->Image = Image;
> + HttpIo->Controller = Controller;
> + HttpIo->IpVersion = IpVersion;
> + HttpIo->Http = Http;
> + HttpIo->Callback = Callback;
> + HttpIo->Context = Context;
> +
> + if (ConfigData != NULL) {
> + if (HttpIo->IpVersion == IP_VERSION_4) {
> + HttpConfigData.LocalAddressIsIPv6 = FALSE;
> + HttpConfigData.HttpVersion = ConfigData->Config4.HttpVersion;
> + HttpConfigData.TimeOutMillisec = ConfigData->Config4.RequestTimeOut;
> +
> + Http4AccessPoint.UseDefaultAddress = ConfigData->Config4.UseDefaultAddress;
> + Http4AccessPoint.LocalPort = ConfigData->Config4.LocalPort;
> + IP4_COPY_ADDRESS (&Http4AccessPoint.LocalAddress, &ConfigData->Config4.LocalIp);
> + IP4_COPY_ADDRESS (&Http4AccessPoint.LocalSubnet, &ConfigData->Config4.SubnetMask);
> + HttpConfigData.AccessPoint.IPv4Node = &Http4AccessPoint;
> + } else {
> + HttpConfigData.LocalAddressIsIPv6 = TRUE;
> + HttpConfigData.HttpVersion = ConfigData->Config6.HttpVersion;
> + HttpConfigData.TimeOutMillisec = ConfigData->Config6.RequestTimeOut;
> +
> + Http6AccessPoint.LocalPort = ConfigData->Config6.LocalPort;
> + IP6_COPY_ADDRESS (&Http6AccessPoint.LocalAddress, &ConfigData->Config6.LocalIp);
> + HttpConfigData.AccessPoint.IPv6Node = &Http6AccessPoint;
> + }
> +
> + Status = Http->Configure (Http, &HttpConfigData);
> + if (EFI_ERROR (Status)) {
> + goto ON_ERROR;
> + }
> + }
> +
> + //
> + // Create events for variuos asynchronous operations.
> + //
> + Status = gBS->CreateEvent (
> + EVT_NOTIFY_SIGNAL,
> + TPL_NOTIFY,
> + HttpIoNotify,
> + &HttpIo->IsTxDone,
> + &Event
> + );
> + if (EFI_ERROR (Status)) {
> + goto ON_ERROR;
> + }
> + HttpIo->ReqToken.Event = Event;
> + HttpIo->ReqToken.Message = &HttpIo->ReqMessage;
> +
> + Status = gBS->CreateEvent (
> + EVT_NOTIFY_SIGNAL,
> + TPL_NOTIFY,
> + HttpIoNotify,
> + &HttpIo->IsRxDone,
> + &Event
> + );
> + if (EFI_ERROR (Status)) {
> + goto ON_ERROR;
> + }
> + HttpIo->RspToken.Event = Event;
> + HttpIo->RspToken.Message = &HttpIo->RspMessage;
> +
> + //
> + // Create TimeoutEvent for response
> + //
> + Status = gBS->CreateEvent (
> + EVT_TIMER,
> + TPL_CALLBACK,
> + NULL,
> + NULL,
> + &Event
> + );
> + if (EFI_ERROR (Status)) {
> + goto ON_ERROR;
> + }
> + HttpIo->TimeoutEvent = Event;
> + return EFI_SUCCESS;
> +
> +ON_ERROR:
> + HttpIoDestroyIo (HttpIo);
> +
> + return Status;
> +}
> +
> +/**
> + Synchronously send a HTTP REQUEST message to the server.
> +
> + @param[in] HttpIo The HttpIo wrapping the HTTP service.
> + @param[in] Request A pointer to storage such data as URL and HTTP method.
> + @param[in] HeaderCount Number of HTTP header structures in Headers list.
> + @param[in] Headers Array containing list of HTTP headers.
> + @param[in] BodyLength Length in bytes of the HTTP body.
> + @param[in] Body Body associated with the HTTP request.
> +
> + @retval EFI_SUCCESS The HTTP request is trasmitted.
> + @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
> + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
> + @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
> + @retval Others Other errors as indicated.
> +
> +**/
> +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
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HTTP_PROTOCOL *Http;
> +
> + if (HttpIo == NULL || HttpIo->Http == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + HttpIo->ReqToken.Status = EFI_NOT_READY;
> + HttpIo->ReqToken.Message->Data.Request = Request;
> + HttpIo->ReqToken.Message->HeaderCount = HeaderCount;
> + HttpIo->ReqToken.Message->Headers = Headers;
> + HttpIo->ReqToken.Message->BodyLength = BodyLength;
> + HttpIo->ReqToken.Message->Body = Body;
> +
> + if (HttpIo->Callback != NULL) {
> + Status = HttpIo->Callback (
> + HttpIoRequest,
> + HttpIo->ReqToken.Message,
> + HttpIo->Context
> + );
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + }
> +
> + //
> + // Queue the request token to HTTP instances.
> + //
> + Http = HttpIo->Http;
> + HttpIo->IsTxDone = FALSE;
> + Status = Http->Request (
> + Http,
> + &HttpIo->ReqToken
> + );
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + //
> + // Poll the network until transmit finish.
> + //
> + while (!HttpIo->IsTxDone) {
> + Http->Poll (Http);
> + }
> +
> + return HttpIo->ReqToken.Status;
> +}
> +
> +/**
> + Synchronously receive a HTTP RESPONSE message from the server.
> +
> + @param[in] HttpIo The HttpIo wrapping the HTTP service.
> + @param[in] RecvMsgHeader TRUE to receive a new HTTP response (from message header).
> + FALSE to continue receive the previous response message.
> + @param[out] ResponseData Point to a wrapper of the received response data.
> +
> + @retval EFI_SUCCESS The HTTP response is received.
> + @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
> + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
> + @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
> + @retval Others Other errors as indicated.
> +
> +**/
> +EFI_STATUS
> +HttpIoRecvResponse (
> + IN HTTP_IO *HttpIo,
> + IN BOOLEAN RecvMsgHeader,
> + OUT HTTP_IO_RESPONSE_DATA *ResponseData
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HTTP_PROTOCOL *Http;
> +
> + if (HttpIo == NULL || HttpIo->Http == NULL || ResponseData == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // Queue the response token to HTTP instances.
> + //
> + HttpIo->RspToken.Status = EFI_NOT_READY;
> + if (RecvMsgHeader) {
> + HttpIo->RspToken.Message->Data.Response = &ResponseData->Response;
> + } else {
> + HttpIo->RspToken.Message->Data.Response = NULL;
> + }
> + HttpIo->RspToken.Message->HeaderCount = 0;
> + HttpIo->RspToken.Message->Headers = NULL;
> + HttpIo->RspToken.Message->BodyLength = ResponseData->BodyLength;
> + HttpIo->RspToken.Message->Body = ResponseData->Body;
ResponseData in function header is set as OUT. Since we are actually
using data inside it, it should be IN OUT.
Please fix that in code and parameter comments.
> +
> + Http = HttpIo->Http;
> + HttpIo->IsRxDone = FALSE;
> +
> + //
> + // Start the timer, and wait Timeout seconds to receive the header packet.
> + //
> + Status = gBS->SetTimer (HttpIo->TimeoutEvent, TimerRelative, HttpIo->Timeout * TICKS_PER_MS);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = Http->Response (
> + Http,
> + &HttpIo->RspToken
> + );
> +
> + if (EFI_ERROR (Status)) {
> + //
> + // Remove timeout timer from the event list.
> + //
> + gBS->SetTimer (HttpIo->TimeoutEvent, TimerCancel, 0);
> + return Status;
> + }
> +
> + //
> + // Poll the network until receive finish.
> + //
> + while (!HttpIo->IsRxDone && EFI_ERROR (gBS->CheckEvent (HttpIo->TimeoutEvent))) {
> + Http->Poll (Http);
> + }
> +
> + //
> + // Remove timeout timer from the event list.
> + //
> + gBS->SetTimer (HttpIo->TimeoutEvent, TimerCancel, 0);
> +
> + if (!HttpIo->IsRxDone) {
> + //
> + // Timeout occurs, cancel the response token.
> + //
> + Http->Cancel (Http, &HttpIo->RspToken);
> +
> + Status = EFI_TIMEOUT;
> +
> + return Status;
> + } else {
> + HttpIo->IsRxDone = FALSE;
> + }
> +
> + if ((HttpIo->Callback != NULL) &&
> + (HttpIo->RspToken.Status == EFI_SUCCESS || HttpIo->RspToken.Status == EFI_HTTP_ERROR)) {
> + Status = HttpIo->Callback (
> + HttpIoResponse,
> + HttpIo->RspToken.Message,
> + HttpIo->Context
> + );
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + }
> +
> + //
> + // Store the received data into the wrapper.
> + //
> + ResponseData->Status = HttpIo->RspToken.Status;
> + ResponseData->HeaderCount = HttpIo->RspToken.Message->HeaderCount;
> + ResponseData->Headers = HttpIo->RspToken.Message->Headers;
> + ResponseData->BodyLength = HttpIo->RspToken.Message->BodyLength;
> +
> + return Status;
> +}
> +
> +/**
> + Get the value of the content length if there is a "Content-Length" header.
> +
> + @param[in] HeaderCount Number of HTTP header structures in Headers.
> + @param[in] Headers Array containing list of HTTP headers.
> + @param[out] ContentLength Pointer to save the value of the content length.
> +
> + @retval EFI_SUCCESS Successfully get the content length.
> + @retval EFI_NOT_FOUND No "Content-Length" header in the Headers.
> +
> +**/
> +EFI_STATUS
> +HttpIoGetContentLength (
> + IN UINTN HeaderCount,
> + IN EFI_HTTP_HEADER *Headers,
> + OUT UINTN *ContentLength
> + )
> +{
> + EFI_HTTP_HEADER *Header;
> +
> + Header = HttpFindHeader (HeaderCount, Headers, HTTP_HEADER_CONTENT_LENGTH);
> + if (Header == NULL) {
> + return EFI_NOT_FOUND;
> + }
> +
> + return AsciiStrDecimalToUintnS (Header->FieldValue, (CHAR8 **) NULL, ContentLength);
> +}
> +/**
> + Send HTTP request in chunks.
> +
> + @param[in] HttpIo The HttpIo wrapping the HTTP service.
> + @param[in] SendChunkProcess Pointer to current chunk process status.
> + @param[in] RequestMessage Request to send.
> +
> + @retval EFI_SUCCESS Successfully to send chunk data according to SendChunkProcess.
> + @retval Other Other errors.
> +
> +**/
> +EFI_STATUS
> +HttpIoSendChunkedTransfer (
> + IN HTTP_IO *HttpIo,
> + IN HTTP_IO_SEND_CHUNK_PROCESS *SendChunkProcess,
> + IN EFI_HTTP_MESSAGE *RequestMessage
> +)
> +{
> + EFI_STATUS Status;
> + EFI_HTTP_HEADER *NewHeaders;
> + EFI_HTTP_HEADER *ContentLengthHeader;
> + UINTN AddNewHeader;
> + UINTN HeaderCount;
> + CHAR8 *MessageBody;
> + UINTN MessageBodyLength;
> + CHAR8 ChunkLengthStr [HTTP_IO_CHUNK_SIZE_STRING_LEN];
> + EFI_HTTP_REQUEST_DATA *SentRequestData;
> +
> + AddNewHeader = 0;
> + NewHeaders = NULL;
> + MessageBody = NULL;
> + ContentLengthHeader = NULL;
> + MessageBodyLength = 0;
> +
> + switch (*SendChunkProcess) {
> + case HttpIoSendChunkHeaderZeroContent:
> + ContentLengthHeader = HttpFindHeader (RequestMessage->HeaderCount, RequestMessage->Headers, HTTP_HEADER_CONTENT_LENGTH);
> + if (ContentLengthHeader == NULL) {
> + AddNewHeader = 1;
> + }
> +
> + NewHeaders = AllocateZeroPool ((RequestMessage->HeaderCount + AddNewHeader) * sizeof(EFI_HTTP_HEADER));
> + CopyMem ((VOID*)NewHeaders, (VOID *)RequestMessage->Headers, RequestMessage->HeaderCount * sizeof (EFI_HTTP_HEADER));
> + if (AddNewHeader == 0) {
> + //
> + // Override content-length to Transfer-Encoding.
> + //
> + ContentLengthHeader = HttpFindHeader (RequestMessage->HeaderCount, NewHeaders, HTTP_HEADER_CONTENT_LENGTH);
> + ContentLengthHeader->FieldName = NULL;
> + ContentLengthHeader->FieldValue = NULL;
> + } else {
> + ContentLengthHeader = NewHeaders + RequestMessage->HeaderCount;
> + }
> + HttpSetFieldNameAndValue (ContentLengthHeader, HTTP_HEADER_TRANSFER_ENCODING, HTTP_HEADER_TRANSFER_ENCODING_CHUNKED);
> + HeaderCount = RequestMessage->HeaderCount + AddNewHeader;
> + MessageBodyLength = 0;
> + MessageBody = NULL;
> + SentRequestData = RequestMessage->Data.Request;
> + break;
> +
> + case HttpIoSendChunkContent:
> + HeaderCount = 0;
> + NewHeaders = NULL;
> + SentRequestData = NULL;
> + if (RequestMessage->BodyLength > HTTP_IO_MAX_SEND_PAYLOAD) {
> + MessageBodyLength = HTTP_IO_MAX_SEND_PAYLOAD;
> + } else {
> + MessageBodyLength = RequestMessage->BodyLength;
> + }
> + AsciiSPrint (
> + ChunkLengthStr,
> + HTTP_IO_CHUNK_SIZE_STRING_LEN,
> + "%x%c%c",
> + MessageBodyLength,
> + CHUNKED_TRANSFER_CODING_CR,
> + CHUNKED_TRANSFER_CODING_LF
> + );
Function breaks should be off by 2 spaces, not 4 :)
This applies to other broken-down calls in chunked send/receive functions.
> + MessageBody = AllocatePool (AsciiStrLen (ChunkLengthStr) + MessageBodyLength + 2);
> + if (MessageBody == NULL) {
> + DEBUG((DEBUG_ERROR, "Not enough memory for chunk transfer\n"));
> + return EFI_OUT_OF_RESOURCES;
> + }
> + //
> + // Build up the chunk transfer paylaod.
> + //
> + CopyMem (MessageBody, ChunkLengthStr, AsciiStrLen (ChunkLengthStr));
AsciiStrLen is used a lot here. It could be called once and stored in
variable.
> + CopyMem (MessageBody + AsciiStrLen (ChunkLengthStr), RequestMessage->Body, MessageBodyLength);
> + *(MessageBody + AsciiStrLen (ChunkLengthStr) + MessageBodyLength) = CHUNKED_TRANSFER_CODING_CR;
> + *(MessageBody + AsciiStrLen (ChunkLengthStr) + MessageBodyLength + 1) = CHUNKED_TRANSFER_CODING_LF;
> + //
> + // Change variables for the next chunk trasnfer.
> + //
> + RequestMessage->BodyLength -= MessageBodyLength;
> + RequestMessage->Body = (VOID *)((CHAR8 *)RequestMessage->Body + MessageBodyLength);
> + MessageBodyLength += (AsciiStrLen (ChunkLengthStr) + 2);
> + if (RequestMessage->BodyLength == 0) {
> + *SendChunkProcess = HttpIoSendChunkEndChunk;
> + }
> + break;
> +
> + case HttpIoSendChunkEndChunk:
> + HeaderCount = 0;
> + NewHeaders = NULL;
> + SentRequestData = NULL;
> + AsciiSPrint (
> + ChunkLengthStr,
> + HTTP_IO_CHUNK_SIZE_STRING_LEN,
> + "0%c%c%c%c",
> + CHUNKED_TRANSFER_CODING_CR,
> + CHUNKED_TRANSFER_CODING_LF,
> + CHUNKED_TRANSFER_CODING_CR,
> + CHUNKED_TRANSFER_CODING_LF
> + );
> + MessageBody = AllocatePool (AsciiStrLen(ChunkLengthStr));
> + if (MessageBody == NULL) {
> + DEBUG((DEBUG_ERROR, "Not enough memory for the end chunk transfer\n"));
> + return EFI_OUT_OF_RESOURCES;
> + }
> + CopyMem (MessageBody, ChunkLengthStr, AsciiStrLen (ChunkLengthStr));
> + MessageBodyLength = AsciiStrLen (ChunkLengthStr);
> + *SendChunkProcess = HttpIoSendChunkFinish;
> + break;
> +
> + default:
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Status = HttpIoSendRequest (
> + HttpIo,
> + SentRequestData,
> + HeaderCount,
> + NewHeaders,
> + MessageBodyLength,
> + MessageBody
> + );
> + if (ContentLengthHeader != NULL) {
> + if (ContentLengthHeader->FieldName != NULL) {
> + FreePool (ContentLengthHeader->FieldName);
> + }
> + if (ContentLengthHeader->FieldValue != NULL) {
> + FreePool (ContentLengthHeader->FieldValue);
> + }
> + }
> + if (NewHeaders != NULL) {
> + FreePool (NewHeaders);
> + }
> + if (MessageBody != NULL) {
> + FreePool (MessageBody);
> + }
> + return Status;
> +}
> +
> +/**
> + Synchronously receive a HTTP RESPONSE message from the server.
> +
> + @param[in] HttpIo The HttpIo wrapping the HTTP service.
> + @param[in] HeaderCount Number of headers in Headers.
> + @param[in] Headers Array containing list of HTTP headers.
> + @param[out] ChunkListHead A pointer to receive list head
> + of chunked data. Caller has to
> + release memory of ChunkListHead
> + and all list entries.
> + @param[out] ContentLength Total content length
> +
> + @retval EFI_SUCCESS The HTTP chunked transfer is received.
> + @retval EFI_NOT_FOUND No chunked transfer coding header found.
> + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
> + @retval EFI_INVALID_PARAMETER Improper parameters.
> + @retval Others Other errors as indicated.
> +
> +**/
> +EFI_STATUS
> +HttpIoGetChunkedTransferContent (
> + IN HTTP_IO *HttpIo,
> + IN UINTN HeaderCount,
> + IN EFI_HTTP_HEADER *Headers,
> + OUT LIST_ENTRY **ChunkListHead,
> + OUT UINTN *ContentLength
> + )
> +{
> + EFI_HTTP_HEADER *Header;
> + CHAR8 ChunkSizeAscii [256];
> + EFI_STATUS Status;
> + UINTN Index;
> + HTTP_IO_RESPONSE_DATA ResponseData;
> + UINTN TotalLength;
> + LIST_ENTRY *HttpChunks;
> + HTTP_IO_CHUNKS *ThisChunk;
> + LIST_ENTRY *ThisListEntry;
> +
> + if (ChunkListHead == NULL || ContentLength == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + *ContentLength = 0;
> + Header = HttpFindHeader (HeaderCount, Headers, HTTP_HEADER_TRANSFER_ENCODING);
> + if (Header == NULL) {
> + return EFI_NOT_FOUND;
> + }
> + if (AsciiStrCmp (Header->FieldValue, HTTP_HEADER_TRANSFER_ENCODING_CHUNKED) != 0) {
> + return EFI_NOT_FOUND;
> + }
Please add a bit of vertical spacing between "blocks" of code that
perform a logical subroutine inside this function (parameter prep,
function call, result, spacing).
It really is easier to read!
> + //
> + // Loop to get all chunks.
> + //
> + TotalLength = 0;
> + HttpChunks = (LIST_ENTRY *)AllocateZeroPool (sizeof (LIST_ENTRY));
> + if (HttpChunks == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto ExitDeleteChunks;
> + }
> + InitializeListHead (HttpChunks);
> + DEBUG ((DEBUG_INFO, " Chunked transfer\n"));
> + while (TRUE) {
> + ZeroMem((VOID *)&ResponseData, sizeof(HTTP_IO_RESPONSE_DATA));
> + ResponseData.BodyLength = HTTP_IO_CHUNKED_TRANSFER_CODING_DATA_LENGTH;
> + ResponseData.Body = ChunkSizeAscii;
> + Status = HttpIoRecvResponse (
> + HttpIo,
> + FALSE,
> + &ResponseData
> + );
> + if (EFI_ERROR (Status)) {
> + goto ExitDeleteChunks;
> + }
> + //
> + // Decoding Chunked Transfer Coding.
> + // Only decode chunk-size and last chunk.
> + //
> + DEBUG ((DEBUG_INFO, " Chunk HTTP Response StatusCode - %d\n", ResponseData.Response.StatusCode));
> + //
> + // Break if this is last chunk.
> + //
> + if (ChunkSizeAscii [0] == CHUNKED_TRANSFER_CODING_LAST_CHUNK) {
> + Status = EFI_SUCCESS;
> + DEBUG ((DEBUG_INFO, " Last chunk\n"));
> + ThisChunk = (HTTP_IO_CHUNKS *)AllocateZeroPool (sizeof (HTTP_IO_CHUNKS));
> + if (ThisChunk == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto ExitDeleteChunks;
> + }
> + InitializeListHead (&ThisChunk->NextChunk);
> + ThisChunk->Length = ResponseData.BodyLength - 1 - 2; // Minus sizeof '0' and CRLF.
How do we know that the chunk we have received even contains 0 and CRLF?
I would suggest adding minimal chunk length validation or else
ThisChunk->Length might underflow.
> + ThisChunk->Data = (CHAR8 *)AllocatePool (ThisChunk->Length);
> + if (ThisChunk->Data == NULL) {
> + FreePool ((UINT8 *)ThisChunk);
> + Status = EFI_OUT_OF_RESOURCES;
> + goto ExitDeleteChunks;
> + }
> + CopyMem ((UINT8 *)ThisChunk->Data, (UINT8 *)ResponseData.Body + 1, ThisChunk->Length);
> + TotalLength += ThisChunk->Length;
> + InsertTailList (HttpChunks, &ThisChunk->NextChunk);
> + break;
> + }
> +
> + //
> + // Get the chunk length
> + //
> + Index = 0;
> + while ((ChunkSizeAscii [Index] != CHUNKED_TRANSFER_CODING_EXTENSION_SEPARATOR) &&
> + (ChunkSizeAscii [Index] != (CHAR8)CHUNKED_TRANSFER_CODING_CR) &&
> + (Index != HTTP_IO_CHUNKED_TRANSFER_CODING_DATA_LENGTH)) {
> + Index ++;
> + };
Comma after while block - please remove.
> + if (Index == HTTP_IO_CHUNKED_TRANSFER_CODING_DATA_LENGTH) {
> + Status = EFI_NOT_FOUND;
> + goto ExitDeleteChunks;
> + }
> + ChunkSizeAscii[Index] = 0;
> + AsciiStrHexToUintnS (ChunkSizeAscii, NULL, ContentLength);
> + DEBUG ((DEBUG_INFO, " Length of this chunk %d\n", *ContentLength));
I do not trust chunk input. If *ContentLength is something huge, we
might overflow TotalLength.
Knowing the message length (ResponseData.BodyLength), we could obtain
how much space the actual chunk can occupy.
It would be good to verify *ContentLength against the size of that
space, so that we do not allocate some huge block later.
> + //
> + // Receive the data;
> + //
> + ThisChunk = (HTTP_IO_CHUNKS *)AllocateZeroPool (sizeof (HTTP_IO_CHUNKS));
> + if (ThisChunk == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto ExitDeleteChunks;
> + }
> + ResponseData.BodyLength = *ContentLength;
> + ResponseData.Body = (CHAR8 *)AllocatePool (*ContentLength);
> + if (ResponseData.Body == NULL) {
> + FreePool (ThisChunk);
> + Status = EFI_OUT_OF_RESOURCES;
> + goto ExitDeleteChunks;
> + }
> + InitializeListHead (&ThisChunk->NextChunk);
> + ThisChunk->Length = *ContentLength;
> + ThisChunk->Data = ResponseData.Body;
> + InsertTailList (HttpChunks, &ThisChunk->NextChunk);
> + Status = HttpIoRecvResponse (
> + HttpIo,
> + FALSE,
> + &ResponseData
> + );
> + if (EFI_ERROR (Status)) {
> + goto ExitDeleteChunks;
> + }
> + //
> + // Read CRLF
> + //
> + ZeroMem((VOID *)&ResponseData, sizeof(HTTP_IO_RESPONSE_DATA));
Spacing after function name.
> + ResponseData.BodyLength = 2;
> + ResponseData.Body = ChunkSizeAscii;
> + Status = HttpIoRecvResponse (
> + HttpIo,
> + FALSE,
> + &ResponseData
> + );
> + if (EFI_ERROR (Status)) {
> + goto ExitDeleteChunks;
> + }
> +
> + TotalLength += *ContentLength;
> + };
Comma after while block. Please remove.
> +
> + *ContentLength = TotalLength;
> + *ChunkListHead = HttpChunks;
> + DEBUG ((DEBUG_INFO, " Total of lengh of chunks :%d\n", TotalLength));
> + return EFI_SUCCESS;
> +
> +ExitDeleteChunks:
> + if (HttpChunks != NULL) {
> + while (!IsListEmpty(HttpChunks)) {
> + ThisListEntry = GetFirstNode (HttpChunks);
> + RemoveEntryList (ThisListEntry);
> + ThisChunk = (HTTP_IO_CHUNKS *)ThisListEntry;
> + if (ThisChunk->Data != NULL) {
> + FreePool (ThisChunk->Data);
> + }
> + FreePool(ThisListEntry);
> + };
Comma after while block. Please remove.
> + FreePool (HttpChunks);
> + }
> + return Status;
> +}
> diff --git a/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.inf b/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.inf
> new file mode 100644
> index 0000000000..a02b409547
> --- /dev/null
> +++ b/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.inf
> @@ -0,0 +1,43 @@
> +## @file
> +# This library instance provides HTTP IO helper functions.
> +#
> +# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> + INF_VERSION = 0x0001001b
> + BASE_NAME = DxeHttpIoLib
> + MODULE_UNI_FILE = DxeHttpIoLib.uni
> + FILE_GUID = 50B198F8-7986-4F51-A857-CFE4643D59F3
> + MODULE_TYPE = DXE_DRIVER
> + VERSION_STRING = 1.0
> + LIBRARY_CLASS = HttpIoLib| DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +# VALID_ARCHITECTURES = IA32 X64 EBC ARM AARM64 RISCV64
> +#
> +
> +[Sources]
> + DxeHttpIoLib.c
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> + NetworkPkg/NetworkPkg.dec
> +
> +
> +[LibraryClasses]
> + BaseLib
> + BaseMemoryLib
> + DebugLib
> + DpcLib
> + MemoryAllocationLib
> + PrintLib
> + UefiBootServicesTableLib
> +
> +[Protocols]
> + gEfiHttpProtocolGuid ## SOMETIMES_CONSUMES
> +
> diff --git a/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.uni b/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.uni
> new file mode 100644
> index 0000000000..d419b1a49d
> --- /dev/null
> +++ b/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.uni
> @@ -0,0 +1,13 @@
> +// /** @file
> +// The library instance provides HTTP IO helper functions.
> +//
> +// (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT #language en-US "HTTP IO Helper Library"
> +
> +#string STR_MODULE_DESCRIPTION #language en-US "The library instance provides HTTP IO helper functions."
> +
next prev parent reply other threads:[~2020-10-28 18:57 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-10-26 6:05 [DxeHttpIoLib PATCH V3 0/3] Add Http IO Helper Library Abner Chang
2020-10-26 6:05 ` [DxeHttpIoLib PATCH V3 1/3] NetworkPkg/Library: Implementation of " Abner Chang
2020-10-28 18:57 ` Maciej Rabeda [this message]
2020-10-29 14:24 ` Abner Chang
2020-10-26 6:05 ` [DxeHttpIoLib PATCH V3 2/3] NetworkPkg: Add Http IO Helper Library to NetworkPkg Abner Chang
2020-10-26 6:05 ` [DxeHttpIoLib PATCH V3 3/3] NetworkPkg/HttpBootDxe: Utilize HttpIoLib Abner Chang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6a4f6c0f-dadc-8aef-c56e-cb946b0640ca@linux.intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox