File shim-httpboot-support.patch of Package shim

From fa1e44d19d6a622241b5411039421976c674bd0f Mon Sep 17 00:00:00 2001
From: Gary Ching-Pang Lin <glin@suse.com>
Date: Tue, 13 Oct 2015 18:18:25 +0800
Subject: [PATCH 1/3] Make translate_slashes() public

Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>
---
 include/str.h | 20 ++++++++++++++++++++
 netboot.c     | 18 ------------------
 2 files changed, 20 insertions(+), 18 deletions(-)

diff --git a/include/str.h b/include/str.h
index 0f3e003..9a74836 100644
--- a/include/str.h
+++ b/include/str.h
@@ -42,4 +42,24 @@ strcata(CHAR8 *dest, const CHAR8 *src)
 	return dest;
 }
 
+static inline
+__attribute__((unused))
+CHAR8 *
+translate_slashes(char *str)
+{
+	int i;
+	int j;
+	if (str == NULL)
+		return (CHAR8 *)str;
+
+	for (i = 0, j = 0; str[i] != '\0'; i++, j++) {
+		if (str[i] == '\\') {
+			str[j] = '/';
+			if (str[i+1] == '\\')
+				i++;
+		}
+	}
+	return (CHAR8 *)str;
+}
+
 #endif /* SHIM_STR_H */
diff --git a/netboot.c b/netboot.c
index ad5d37e..1cc1a2b 100644
--- a/netboot.c
+++ b/netboot.c
@@ -54,24 +54,6 @@ typedef struct {
 	UINT8 Data[1];
 } EFI_DHCP6_PACKET_OPTION;
 
-static CHAR8 *
-translate_slashes(char *str)
-{
-	int i;
-	int j;
-	if (str == NULL)
-		return (CHAR8 *)str;
-
-	for (i = 0, j = 0; str[i] != '\0'; i++, j++) {
-		if (str[i] == '\\') {
-			str[j] = '/';
-			if (str[i+1] == '\\')
-				i++;
-		}
-	}
-	return (CHAR8 *)str;
-}
-
 /*
  * usingNetboot
  * Returns TRUE if we identify a protocol that is enabled and Providing us with
-- 
2.7.1


From 6d6091c59660435e76a922daa76891928c878ae6 Mon Sep 17 00:00:00 2001
From: Gary Ching-Pang Lin <glin@suse.com>
Date: Wed, 14 Oct 2015 16:59:22 +0800
Subject: [PATCH 2/3] Add HTTP and IpConfig headers

Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>
---
 include/Http.h       | 517 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/Ip4Config2.h | 315 +++++++++++++++++++++++++++++++
 include/Ip6Config.h  | 366 ++++++++++++++++++++++++++++++++++++
 3 files changed, 1198 insertions(+)
 create mode 100644 include/Http.h
 create mode 100644 include/Ip4Config2.h
 create mode 100644 include/Ip6Config.h

diff --git a/include/Http.h b/include/Http.h
new file mode 100644
index 0000000..cd77703
--- /dev/null
+++ b/include/Http.h
@@ -0,0 +1,517 @@
+/** @file
+  This file defines the EFI HTTP Protocol interface. It is split into
+  the following two main sections:
+  HTTP Service Binding Protocol (HTTPSB)
+  HTTP Protocol (HTTP)
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution. The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Revision Reference:
+  This Protocol is introduced in UEFI Specification 2.5
+
+**/
+
+#ifndef __EFI_HTTP_PROTOCOL_H__
+#define __EFI_HTTP_PROTOCOL_H__
+
+#define EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID \
+  { \
+    0xbdc8e6af, 0xd9bc, 0x4379, {0xa7, 0x2a, 0xe0, 0xc4, 0xe7, 0x5d, 0xae, 0x1c } \
+  }
+
+#define EFI_HTTP_PROTOCOL_GUID \
+  { \
+    0x7a59b29b, 0x910b, 0x4171, {0x82, 0x42, 0xa8, 0x5a, 0x0d, 0xf2, 0x5b, 0x5b } \
+  }
+
+typedef struct _EFI_HTTP_PROTOCOL EFI_HTTP_PROTOCOL;
+
+///
+/// EFI_HTTP_VERSION
+///
+typedef enum {
+  HttpVersion10,
+  HttpVersion11,
+  HttpVersionUnsupported
+} EFI_HTTP_VERSION;
+
+///
+/// EFI_HTTP_METHOD
+///
+typedef enum {
+  HttpMethodGet,
+  HttpMethodPost,
+  HttpMethodPatch,
+  HttpMethodOptions,
+  HttpMethodConnect,
+  HttpMethodHead,
+  HttpMethodPut,
+  HttpMethodDelete,
+  HttpMethodTrace,
+  HttpMethodMax
+} EFI_HTTP_METHOD;
+
+///
+/// EFI_HTTP_STATUS_CODE
+///
+typedef enum {
+  HTTP_STATUS_UNSUPPORTED_STATUS = 0,
+  HTTP_STATUS_100_CONTINUE,
+  HTTP_STATUS_101_SWITCHING_PROTOCOLS,
+  HTTP_STATUS_200_OK,
+  HTTP_STATUS_201_CREATED,
+  HTTP_STATUS_202_ACCEPTED,
+  HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION,
+  HTTP_STATUS_204_NO_CONTENT,
+  HTTP_STATUS_205_RESET_CONTENT,
+  HTTP_STATUS_206_PARTIAL_CONTENT,
+  HTTP_STATUS_300_MULTIPLE_CHIOCES,
+  HTTP_STATUS_301_MOVED_PERMANENTLY,
+  HTTP_STATUS_302_FOUND,
+  HTTP_STATUS_303_SEE_OTHER,
+  HTTP_STATUS_304_NOT_MODIFIED,
+  HTTP_STATUS_305_USE_PROXY,
+  HTTP_STATUS_307_TEMPORARY_REDIRECT,
+  HTTP_STATUS_400_BAD_REQUEST,
+  HTTP_STATUS_401_UNAUTHORIZED,
+  HTTP_STATUS_402_PAYMENT_REQUIRED,
+  HTTP_STATUS_403_FORBIDDEN,
+  HTTP_STATUS_404_NOT_FOUND,
+  HTTP_STATUS_405_METHOD_NOT_ALLOWED,
+  HTTP_STATUS_406_NOT_ACCEPTABLE,
+  HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED,
+  HTTP_STATUS_408_REQUEST_TIME_OUT,
+  HTTP_STATUS_409_CONFLICT,
+  HTTP_STATUS_410_GONE,
+  HTTP_STATUS_411_LENGTH_REQUIRED,
+  HTTP_STATUS_412_PRECONDITION_FAILED,
+  HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE,
+  HTTP_STATUS_414_REQUEST_URI_TOO_LARGE,
+  HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE,
+  HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED,
+  HTTP_STATUS_417_EXPECTATION_FAILED,
+  HTTP_STATUS_500_INTERNAL_SERVER_ERROR,
+  HTTP_STATUS_501_NOT_IMPLEMENTED,
+  HTTP_STATUS_502_BAD_GATEWAY,
+  HTTP_STATUS_503_SERVICE_UNAVAILABLE,
+  HTTP_STATUS_504_GATEWAY_TIME_OUT,
+  HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED
+} EFI_HTTP_STATUS_CODE;
+
+///
+/// EFI_HTTPv4_ACCESS_POINT
+///
+typedef struct {
+  ///
+  /// Set to TRUE to instruct the EFI HTTP instance to use the default address
+  /// information in every TCP connection made by this instance. In addition, when set
+  /// to TRUE, LocalAddress and LocalSubnet are ignored.
+  ///
+  BOOLEAN                       UseDefaultAddress;
+  ///
+  /// If UseDefaultAddress is set to FALSE, this defines the local IP address to be
+  /// used in every TCP connection opened by this instance.
+  ///
+  EFI_IPv4_ADDRESS              LocalAddress;
+  ///
+  /// If UseDefaultAddress is set to FALSE, this defines the local subnet to be used
+  /// in every TCP connection opened by this instance.
+  ///
+  EFI_IPv4_ADDRESS              LocalSubnet;
+  ///
+  /// This defines the local port to be used in
+  /// every TCP connection opened by this instance.
+  ///
+  UINT16                        LocalPort;
+} EFI_HTTPv4_ACCESS_POINT;
+
+///
+/// EFI_HTTPv6_ACCESS_POINT
+///
+typedef struct {
+  ///
+  /// Local IP address to be used in every TCP connection opened by this instance.
+  ///
+  EFI_IPv6_ADDRESS              LocalAddress;
+  ///
+  /// Local port to be used in every TCP connection opened by this instance.
+  ///
+  UINT16                        LocalPort;
+} EFI_HTTPv6_ACCESS_POINT;
+
+///
+/// EFI_HTTP_CONFIG_DATA_ACCESS_POINT
+///
+
+
+typedef struct {
+  ///
+  /// HTTP version that this instance will support.
+  ///
+  EFI_HTTP_VERSION                   HttpVersion;
+  ///
+  /// Time out (in milliseconds) when blocking for requests.
+  ///
+  UINT32                             TimeOutMillisec;
+  ///
+  /// Defines behavior of EFI DNS and TCP protocols consumed by this instance. If
+  /// FALSE, this instance will use EFI_DNS4_PROTOCOL and EFI_TCP4_PROTOCOL. If TRUE,
+  /// this instance will use EFI_DNS6_PROTOCOL and EFI_TCP6_PROTOCOL.
+  ///
+  BOOLEAN                            LocalAddressIsIPv6;
+
+  union {
+    ///
+    /// When LocalAddressIsIPv6 is FALSE, this points to the local address, subnet, and
+    /// port used by the underlying TCP protocol.
+    ///
+    EFI_HTTPv4_ACCESS_POINT          *IPv4Node;
+    ///
+    /// When LocalAddressIsIPv6 is TRUE, this points to the local IPv6 address and port
+    /// used by the underlying TCP protocol.
+    ///
+    EFI_HTTPv6_ACCESS_POINT          *IPv6Node;
+  } AccessPoint;
+} EFI_HTTP_CONFIG_DATA;
+
+///
+/// EFI_HTTP_REQUEST_DATA
+///
+typedef struct {
+  ///
+  /// The HTTP method (e.g. GET, POST) for this HTTP Request.
+  ///
+  EFI_HTTP_METHOD               Method;
+  ///
+  /// The URI of a remote host. From the information in this field, the HTTP instance
+  /// will be able to determine whether to use HTTP or HTTPS and will also be able to
+  /// determine the port number to use. If no port number is specified, port 80 (HTTP)
+  /// is assumed. See RFC 3986 for more details on URI syntax.
+  ///
+  CHAR16                        *Url;
+} EFI_HTTP_REQUEST_DATA;
+
+///
+/// EFI_HTTP_RESPONSE_DATA
+///
+typedef struct {
+  ///
+  /// Response status code returned by the remote host.
+  ///
+  EFI_HTTP_STATUS_CODE          StatusCode;
+} EFI_HTTP_RESPONSE_DATA;
+
+///
+/// EFI_HTTP_HEADER
+///
+typedef struct {
+  ///
+  /// Null terminated string which describes a field name. See RFC 2616 Section 14 for
+  /// detailed information about field names.
+  ///
+  CHAR8                         *FieldName;
+  ///
+  /// Null terminated string which describes the corresponding field value. See RFC 2616
+  /// Section 14 for detailed information about field values.
+  ///
+  CHAR8                         *FieldValue;
+} EFI_HTTP_HEADER;
+
+///
+/// EFI_HTTP_MESSAGE
+///
+typedef struct {
+  ///
+  /// HTTP message data.
+  ///
+  union {
+    ///
+    /// When the token is used to send a HTTP request, Request is a pointer to storage that
+    /// contains such data as URL and HTTP method.
+    ///
+    EFI_HTTP_REQUEST_DATA       *Request;
+    ///
+    /// When used to await a response, Response points to storage containing HTTP response
+    /// status code.
+    ///
+    EFI_HTTP_RESPONSE_DATA      *Response;
+  } Data;
+  ///
+  /// Number of HTTP header structures in Headers list. On request, this count is
+  /// provided by the caller. On response, this count is provided by the HTTP driver.
+  ///
+  UINTN                         HeaderCount;
+  ///
+  /// Array containing list of HTTP headers. On request, this array is populated by the
+  /// caller. On response, this array is allocated and populated by the HTTP driver. It
+  /// is the responsibility of the caller to free this memory on both request and
+  /// response.
+  ///
+  EFI_HTTP_HEADER               *Headers;
+  ///
+  /// Length in bytes of the HTTP body. This can be zero depending on the HttpMethod type.
+  ///
+  UINTN                         BodyLength;
+  ///
+  /// Body associated with the HTTP request or response. This can be NULL depending on
+  /// the HttpMethod type.
+  ///
+  VOID                          *Body;
+} EFI_HTTP_MESSAGE;
+
+
+///
+/// EFI_HTTP_TOKEN
+///
+typedef struct {
+  ///
+  /// This Event will be signaled after the Status field is updated by the EFI HTTP
+  /// Protocol driver. The type of Event must be EFI_NOTIFY_SIGNAL. The Task Priority
+  /// Level (TPL) of Event must be lower than or equal to TPL_CALLBACK.
+  ///
+  EFI_EVENT                     Event;
+  ///
+  /// Status will be set to one of the following value if the HTTP request is
+  /// successfully sent or if an unexpected error occurs:
+  ///   EFI_SUCCESS:      The HTTP request was successfully sent to the remote host.
+  ///   EFI_HTTP_ERROR:   The response message was successfully received but contains a
+  ///                     HTTP error. The response status code is returned in token.
+  ///   EFI_ABORTED:      The HTTP request was cancelled by the caller and removed from
+  ///                     the transmit queue.
+  ///   EFI_TIMEOUT:      The HTTP request timed out before reaching the remote host.
+  ///   EFI_DEVICE_ERROR: An unexpected system or network error occurred.
+  ///
+  EFI_STATUS                    Status;
+  ///
+  /// Pointer to storage containing HTTP message data.
+  ///
+  EFI_HTTP_MESSAGE              *Message;
+} EFI_HTTP_TOKEN;
+
+/**
+  Returns the operational parameters for the current HTTP child instance.
+
+  The GetModeData() function is used to read the current mode data (operational
+  parameters) for this HTTP protocol instance.
+
+  @param[in]  This                Pointer to EFI_HTTP_PROTOCOL instance.
+  @param[out] HttpConfigData      Point to buffer for operational parameters of this
+                                  HTTP instance.
+
+  @retval EFI_SUCCESS             Operation succeeded.
+  @retval EFI_INVALID_PARAMETER   This is NULL.
+                                  HttpConfigData is NULL.
+                                  HttpInstance->LocalAddressIsIPv6 is FALSE and
+                                  HttpConfigData->IPv4Node is NULL.
+                                  HttpInstance->LocalAddressIsIPv6 is TRUE and
+                                  HttpConfigData->IPv6Node is NULL.
+  @retval EFI_NOT_STARTED         This EFI HTTP Protocol instance has not been started.
+**/
+typedef
+EFI_STATUS
+(EFIAPI * EFI_HTTP_GET_MODE_DATA)(
+  IN  EFI_HTTP_PROTOCOL         *This,
+  OUT EFI_HTTP_CONFIG_DATA      *HttpConfigData
+  );
+
+/**
+  Initialize or brutally reset the operational parameters for this EFI HTTP instance.
+
+  The Configure() function does the following:
+  When HttpConfigData is not NULL Initialize this EFI HTTP instance by configuring
+  timeout, local address, port, etc.
+  When HttpConfigData is NULL, reset this EFI HTTP instance by closing all active
+  connections with remote hosts, canceling all asynchronous tokens, and flush request
+  and response buffers without informing the appropriate hosts.
+
+  No other EFI HTTP function can be executed by this instance until the Configure()
+  function is executed and returns successfully.
+
+  @param[in]  This                Pointer to EFI_HTTP_PROTOCOL instance.
+  @param[in]  HttpConfigData      Pointer to the configure data to configure the instance.
+
+  @retval EFI_SUCCESS             Operation succeeded.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  HttpConfigData is NULL.
+                                  HttpConfigData->LocalAddressIsIPv6 is FALSE and
+                                  HttpConfigData->IPv4Node is NULL.
+                                  HttpConfigData->LocalAddressIsIPv6 is TRUE and
+                                  HttpConfigData->IPv6Node is NULL.
+  @retval EFI_ALREADY_STARTED     Reinitialize this HTTP instance without calling
+                                  Configure() with NULL to reset it.
+  @retval EFI_DEVICE_ERROR        An unexpected system or network error occurred.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate enough system resources when
+                                  executing Configure().
+  @retval EFI_UNSUPPORTED         One or more options in ConfigData are not supported
+                                  in the implementation.
+**/
+typedef
+EFI_STATUS
+(EFIAPI * EFI_HTTP_CONFIGURE)(
+  IN  EFI_HTTP_PROTOCOL         *This,
+  IN  EFI_HTTP_CONFIG_DATA      *HttpConfigData
+  );
+
+/**
+  The Request() function queues an HTTP request to this HTTP instance,
+  similar to Transmit() function in the EFI TCP driver. When the HTTP request is sent
+  successfully, or if there is an error, Status in token will be updated and Event will
+  be signaled.
+
+  @param[in]  This                Pointer to EFI_HTTP_PROTOCOL instance.
+  @param[in]  Token               Pointer to storage containing HTTP request token.
+
+  @retval EFI_SUCCESS             Outgoing data was processed.
+  @retval EFI_NOT_STARTED         This EFI HTTP Protocol instance has not been started.
+  @retval EFI_DEVICE_ERROR        An unexpected system or network error occurred.
+  @retval EFI_TIMEOUT             Data was dropped out of the transmit or receive queue.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  Token is NULL.
+                                  Token->Message is NULL.
+                                  Token->Message->Body is not NULL,
+                                  Token->Message->BodyLength is non-zero, and
+                                  Token->Message->Data is NULL, but a previous call to
+                                  Request()has not been completed successfully.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate enough system resources.
+  @retval EFI_UNSUPPORTED         The HTTP method is not supported in current implementation.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HTTP_REQUEST) (
+  IN  EFI_HTTP_PROTOCOL         *This,
+  IN  EFI_HTTP_TOKEN            *Token
+  );
+
+/**
+  Abort an asynchronous HTTP request or response token.
+
+  The Cancel() function aborts a pending HTTP request or response transaction. If
+  Token is not NULL and the token is in transmit or receive queues when it is being
+  cancelled, its Token->Status will be set to EFI_ABORTED and then Token->Event will
+  be signaled. If the token is not in one of the queues, which usually means that the
+  asynchronous operation has completed, EFI_NOT_FOUND is returned. If Token is NULL,
+  all asynchronous tokens issued by Request() or Response() will be aborted.
+
+  @param[in]  This                Pointer to EFI_HTTP_PROTOCOL instance.
+  @param[in]  Token               Point to storage containing HTTP request or response
+                                  token.
+
+  @retval EFI_SUCCESS             Request and Response queues are successfully flushed.
+  @retval EFI_INVALID_PARAMETER   This is NULL.
+  @retval EFI_NOT_STARTED         This instance hasn't been configured.
+  @retval EFI_NOT_FOUND           The asynchronous request or response token is not
+                                  found.
+  @retval EFI_UNSUPPORTED         The implementation does not support this function.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HTTP_CANCEL)(
+  IN  EFI_HTTP_PROTOCOL         *This,
+  IN  EFI_HTTP_TOKEN            *Token
+  );
+
+/**
+  The Response() function queues an HTTP response to this HTTP instance, similar to
+  Receive() function in the EFI TCP driver. When the HTTP Response is received successfully,
+  or if there is an error, Status in token will be updated and Event will be signaled.
+
+  The HTTP driver will queue a receive token to the underlying TCP instance. When data
+  is received in the underlying TCP instance, the data will be parsed and Token will
+  be populated with the response data. If the data received from the remote host
+  contains an incomplete or invalid HTTP header, the HTTP driver will continue waiting
+  (asynchronously) for more data to be sent from the remote host before signaling
+  Event in Token.
+
+  It is the responsibility of the caller to allocate a buffer for Body and specify the
+  size in BodyLength. If the remote host provides a response that contains a content
+  body, up to BodyLength bytes will be copied from the receive buffer into Body and
+  BodyLength will be updated with the amount of bytes received and copied to Body. This
+  allows the client to download a large file in chunks instead of into one contiguous
+  block of memory. Similar to HTTP request, if Body is not NULL and BodyLength is
+  non-zero and all other fields are NULL or 0, the HTTP driver will queue a receive
+  token to underlying TCP instance. If data arrives in the receive buffer, up to
+  BodyLength bytes of data will be copied to Body. The HTTP driver will then update
+  BodyLength with the amount of bytes received and copied to Body.
+
+  If the HTTP driver does not have an open underlying TCP connection with the host
+  specified in the response URL, Request() will return EFI_ACCESS_DENIED. This is
+  consistent with RFC 2616 recommendation that HTTP clients should attempt to maintain
+  an open TCP connection between client and host.
+
+  @param[in]  This                Pointer to EFI_HTTP_PROTOCOL instance.
+  @param[in]  Token               Pointer to storage containing HTTP response token.
+
+  @retval EFI_SUCCESS             Allocation succeeded.
+  @retval EFI_NOT_STARTED         This EFI HTTP Protocol instance has not been
+                                  initialized.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  Token is NULL.
+                                  Token->Message->Headers is NULL.
+                                  Token->Message is NULL.
+                                  Token->Message->Body is not NULL,
+                                  Token->Message->BodyLength is non-zero, and
+                                  Token->Message->Data is NULL, but a previous call to
+                                  Response() has not been completed successfully.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate enough system resources.
+  @retval EFI_ACCESS_DENIED       An open TCP connection is not present with the host
+                                  specified by response URL.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HTTP_RESPONSE) (
+  IN  EFI_HTTP_PROTOCOL         *This,
+  IN  EFI_HTTP_TOKEN            *Token
+  );
+
+/**
+  The Poll() function can be used by network drivers and applications to increase the
+  rate that data packets are moved between the communication devices and the transmit
+  and receive queues.
+
+  In some systems, the periodic timer event in the managed network driver may not poll
+  the underlying communications device fast enough to transmit and/or receive all data
+  packets without missing incoming packets or dropping outgoing packets. Drivers and
+  applications that are experiencing packet loss should try calling the Poll() function
+  more often.
+
+  @param[in]  This                Pointer to EFI_HTTP_PROTOCOL instance.
+
+  @retval EFI_SUCCESS             Incoming or outgoing data was processed..
+  @retval EFI_DEVICE_ERROR        An unexpected system or network error occurred
+  @retval EFI_INVALID_PARAMETER   This is NULL.
+  @retval EFI_NOT_READY           No incoming or outgoing data is processed.
+  @retval EFI_NOT_STARTED         This EFI HTTP Protocol instance has not been started.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HTTP_POLL) (
+  IN  EFI_HTTP_PROTOCOL         *This
+  );
+
+///
+/// The EFI HTTP protocol is designed to be used by EFI drivers and applications to
+/// create and transmit HTTP Requests, as well as handle HTTP responses that are
+/// returned by a remote host. This EFI protocol uses and relies on an underlying EFI
+/// TCP protocol.
+///
+struct _EFI_HTTP_PROTOCOL {
+  EFI_HTTP_GET_MODE_DATA        GetModeData;
+  EFI_HTTP_CONFIGURE            Configure;
+  EFI_HTTP_REQUEST              Request;
+  EFI_HTTP_CANCEL               Cancel;
+  EFI_HTTP_RESPONSE             Response;
+  EFI_HTTP_POLL                 Poll;
+};
+
+#endif
diff --git a/include/Ip4Config2.h b/include/Ip4Config2.h
new file mode 100644
index 0000000..b4f1d84
--- /dev/null
+++ b/include/Ip4Config2.h
@@ -0,0 +1,315 @@
+/** @file
+  This file provides a definition of the EFI IPv4 Configuration II
+  Protocol.
+
+Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at<BR>
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+@par Revision Reference:
+This Protocol is introduced in UEFI Specification 2.5
+
+**/
+#ifndef __EFI_IP4CONFIG2_PROTOCOL_H__
+#define __EFI_IP4CONFIG2_PROTOCOL_H__
+
+#include <efiip.h>
+
+#define EFI_IP4_CONFIG2_PROTOCOL_GUID \
+  { \
+    0x5b446ed1, 0xe30b, 0x4faa, {0x87, 0x1a, 0x36, 0x54, 0xec, 0xa3, 0x60, 0x80 } \
+  }
+
+typedef struct _EFI_IP4_CONFIG2_PROTOCOL EFI_IP4_CONFIG2_PROTOCOL;
+
+
+///
+/// EFI_IP4_CONFIG2_DATA_TYPE
+///
+typedef enum {
+  ///
+  /// The interface information of the communication device this EFI
+  /// IPv4 Configuration II Protocol instance manages. This type of
+  /// data is read only. The corresponding Data is of type
+  /// EFI_IP4_CONFIG2_INTERFACE_INFO.
+  ///
+  Ip4Config2DataTypeInterfaceInfo,
+  ///
+  /// The general configuration policy for the EFI IPv4 network stack
+  /// running on the communication device this EFI IPv4
+  /// Configuration II Protocol instance manages. The policy will
+  /// affect other configuration settings. The corresponding Data is of
+  /// type EFI_IP4_CONFIG2_POLICY.
+  ///
+  Ip4Config2DataTypePolicy,
+  ///
+  /// The station addresses set manually for the EFI IPv4 network
+  /// stack. It is only configurable when the policy is
+  /// Ip4Config2PolicyStatic. The corresponding Data is of
+  /// type EFI_IP4_CONFIG2_MANUAL_ADDRESS.
+  ///
+  Ip4Config2DataTypeManualAddress,
+  ///
+  /// The gateway addresses set manually for the EFI IPv4 network
+  /// stack running on the communication device this EFI IPv4
+  /// Configuration II Protocol manages. It is not configurable when
+  /// the policy is Ip4Config2PolicyDhcp. The gateway
+  /// addresses must be unicast IPv4 addresses. The corresponding
+  /// Data is a pointer to an array of EFI_IPv4_ADDRESS instances.
+  ///
+  Ip4Config2DataTypeGateway,
+  ///
+  /// The DNS server list for the EFI IPv4 network stack running on
+  /// the communication device this EFI IPv4 Configuration II
+  /// Protocol manages. It is not configurable when the policy is
+  /// Ip4Config2PolicyDhcp. The DNS server addresses must be
+  /// unicast IPv4 addresses. The corresponding Data is a pointer to
+  /// an array of EFI_IPv4_ADDRESS instances.
+  ///
+  Ip4Config2DataTypeDnsServer,
+  Ip4Config2DataTypeMaximum
+} EFI_IP4_CONFIG2_DATA_TYPE;
+
+///
+/// EFI_IP4_CONFIG2_INTERFACE_INFO related definitions
+///
+#define EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE 32
+
+///
+/// EFI_IP4_CONFIG2_INTERFACE_INFO
+///
+typedef struct {
+  ///
+  /// The name of the interface. It is a NULL-terminated Unicode string.
+  ///
+  CHAR16                Name[EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE];
+  ///
+  /// The interface type of the network interface. See RFC 1700,
+  /// section "Number Hardware Type".
+  ///
+  UINT8                 IfType;
+  ///
+  /// The size, in bytes, of the network interface's hardware address.
+  ///
+  UINT32                HwAddressSize;
+  ///
+  /// The hardware address for the network interface.
+  ///
+  EFI_MAC_ADDRESS       HwAddress;
+  ///
+  /// The station IPv4 address of this EFI IPv4 network stack.
+  ///
+  EFI_IPv4_ADDRESS      StationAddress;
+  ///
+  /// The subnet address mask that is associated with the station address.
+  ///
+  EFI_IPv4_ADDRESS      SubnetMask;
+  ///
+  /// Size of the following RouteTable, in bytes. May be zero.
+  ///
+  UINT32                RouteTableSize;
+  ///
+  /// The route table of the IPv4 network stack runs on this interface.
+  /// Set to NULL if RouteTableSize is zero. Type EFI_IP4_ROUTE_TABLE is defined in
+  /// EFI_IP4_PROTOCOL.GetModeData().
+  ///
+  EFI_IP4_ROUTE_TABLE   *RouteTable     OPTIONAL;
+} EFI_IP4_CONFIG2_INTERFACE_INFO;
+
+///
+/// EFI_IP4_CONFIG2_POLICY
+///
+typedef enum {
+  ///
+  /// Under this policy, the Ip4Config2DataTypeManualAddress,
+  /// Ip4Config2DataTypeGateway and Ip4Config2DataTypeDnsServer configuration
+  /// data are required to be set manually. The EFI IPv4 Protocol will get all
+  /// required configuration such as IPv4 address, subnet mask and
+  /// gateway settings from the EFI IPv4 Configuration II protocol.
+  ///
+  Ip4Config2PolicyStatic,
+  ///
+  /// Under this policy, the Ip4Config2DataTypeManualAddress,
+  /// Ip4Config2DataTypeGateway and Ip4Config2DataTypeDnsServer configuration data are
+  /// not allowed to set via SetData(). All of these configurations are retrieved from DHCP
+  /// server or other auto-configuration mechanism.
+  ///
+  Ip4Config2PolicyDhcp,
+  Ip4Config2PolicyMax
+} EFI_IP4_CONFIG2_POLICY;
+
+///
+/// EFI_IP4_CONFIG2_MANUAL_ADDRESS
+///
+typedef struct {
+  ///
+  /// The IPv4 unicast address.
+  ///
+  EFI_IPv4_ADDRESS        Address;
+  ///
+  /// The subnet mask.
+  ///
+  EFI_IPv4_ADDRESS        SubnetMask;
+} EFI_IP4_CONFIG2_MANUAL_ADDRESS;
+
+/**
+  Set the configuration for the EFI IPv4 network stack running on the communication device this EFI
+  IPv4 Configuration II Protocol instance manages.
+
+  This function is used to set the configuration data of type DataType for the EFI IPv4 network stack
+  running on the communication device this EFI IPv4 Configuration II Protocol instance manages.
+  The successfully configured data is valid after system reset or power-off.
+  The DataSize is used to calculate the count of structure instances in the Data for some
+  DataType that multiple structure instances are allowed.
+  This function is always non-blocking. When setting some typeof configuration data, an
+  asynchronous process is invoked to check the correctness of the data, such as doing address conflict
+  detection on the manually set local IPv4 address. EFI_NOT_READY is returned immediately to
+  indicate that such an asynchronous process is invoked and the process is not finished yet. The caller
+  willing to get the result of the asynchronous process is required to call RegisterDataNotify()
+  to register an event on the specified configuration data. Once the event is signaled, the caller can call
+  GetData()to get back the configuration data in order to know the result. For other types of
+  configuration data that do not require an asynchronous configuration process, the result of the
+  operation is immediately returned.
+
+  @param[in]   This               Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
+  @param[in]   DataType           The type of data to set.
+  @param[in]   DataSize           Size of the buffer pointed to by Data in bytes.
+  @param[in]   Data               The data buffer to set. The type ofthe data buffer is associated
+                                  with the DataType.
+
+  @retval EFI_SUCCESS             The specified configuration data for the EFI IPv4 network stack is set
+                                  successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following are TRUE:
+                                  This is NULL.
+                                  Data is NULL.
+                                  One or more fields in Data do not match the requirement of the data type
+                                  indicated by DataType.
+  @retval EFI_WRITE_PROTECTED     The specified configuration data is read-only or the specified configuration
+                                  data can not be set under the current policy.
+  @retval EFI_ACCESS_DENIED       Another set operation on the specified configuration data is already in process.
+  @retval EFI_NOT_READY           An asynchronous process is invoked to set the specified configuration data and
+                                  the process is not finished yet.
+  @retval EFI_BAD_BUFFER_SIZE     The DataSize does not match the size of the type indicated by DataType.
+  @retval EFI_UNSUPPORTED         This DataType is not supported.
+  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.
+  @retval EFI_DEVICE_ERROR        An unexpected system error or network error occurred.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP4_CONFIG2_SET_DATA) (
+  IN EFI_IP4_CONFIG2_PROTOCOL   *This,
+  IN EFI_IP4_CONFIG2_DATA_TYPE  DataType,
+  IN UINTN                      DataSize,
+  IN VOID                       *Data
+  );
+
+/**
+  Get the configuration data for the EFI IPv4 network stack running on the communication device this
+  EFI IPv4 Configuration II Protocol instance manages.
+
+  This function returns the configuration data of type DataType for the EFI IPv4 network stack
+  running on the communication device this EFI IPv4 Configuration II Protocol instance manages.
+  The caller is responsible for allocating the buffer usedto return the specified configuration data and
+  the required size will be returned to the caller if the size of the buffer is too small.
+  EFI_NOT_READY is returned if the specified configuration data is not ready due to an already in
+  progress asynchronous configuration process. The caller can call RegisterDataNotify() to
+  register an event on the specified configuration data. Once the asynchronous configuration process is
+  finished, the event will be signaled and a subsequent GetData() call will return the specified
+  configuration data.
+
+  @param[in]   This               Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
+  @param[in]   DataType           The type of data to get.
+  @param[out]  DataSize           On input, in bytes, the size of Data. On output, in bytes, the size
+                                  of buffer required to store the specified configuration data.
+  @param[in]   Data               The data buffer in which the configuration data is returned. The
+                                  type of the data buffer is associated with the DataType. Ignored
+                                  if DataSize is 0.
+
+  @retval EFI_SUCCESS             The specified configuration data is got successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the followings are TRUE:
+                                  This is NULL.
+                                  DataSize is NULL.
+                                  Data is NULL if *DataSizeis not zero.
+  @retval EFI_BUFFER_TOO_SMALL    The size of Data is too small for the specified configuration data
+                                  and the required size is returned in DataSize.
+  @retval EFI_NOT_READY           The specified configuration data is not ready due to an already in
+                                  progress asynchronous configuration process.
+  @retval EFI_NOT_FOUND           The specified configuration data is not found.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP4_CONFIG2_GET_DATA) (
+  IN EFI_IP4_CONFIG2_PROTOCOL     *This,
+  IN EFI_IP4_CONFIG2_DATA_TYPE    DataType,
+  IN OUT UINTN                    *DataSize,
+  IN VOID                         *Data        OPTIONAL
+  );
+
+/**
+  Register an event that is to be signaled whenever a configuration process on the specified
+  configuration data is done.
+
+  This function registers an event that is to be signaled whenever a configuration process on the
+  specified configuration data is done. An event can be registered for different DataType
+  simultaneously and the caller is responsible for determining which type of configuration data causes
+  the signaling of the event in such case.
+
+  @param[in]   This               Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
+  @param[in]   DataType           The type of data to unregister the event for.
+  @param[in]   Event              The event to register.
+
+  @retval EFI_SUCCESS             The notification event for the specified configuration data is
+                                  registered.
+  @retval EFI_INVALID_PARAMETER   This is NULL or Event is NULL.
+  @retval EFI_UNSUPPORTED         The configuration data type specified by DataType is not supported.
+  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.
+  @retval EFI_ACCESS_DENIED       The Event is already registered for the DataType.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP4_CONFIG2_REGISTER_NOTIFY) (
+  IN EFI_IP4_CONFIG2_PROTOCOL     *This,
+  IN EFI_IP4_CONFIG2_DATA_TYPE    DataType,
+  IN EFI_EVENT                    Event
+  );
+
+/**
+  Remove a previously registered event for the specified configuration data.
+
+  This function removes a previously registeredevent for the specified configuration data.
+
+  @param[in]   This               Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
+  @param[in]   DataType           The type of data to remove the previously registered event for.
+  @param[in]   Event              The event to unregister.
+
+  @retval EFI_SUCCESS             The event registered for the specified configuration data is removed.
+  @retval EFI_INVALID_PARAMETER   This is NULL or Event is NULL.
+  @retval EFI_NOT_FOUND           The Eventhas not been registered for the specified DataType.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP4_CONFIG2_UNREGISTER_NOTIFY) (
+  IN EFI_IP4_CONFIG2_PROTOCOL     *This,
+  IN EFI_IP4_CONFIG2_DATA_TYPE    DataType,
+  IN EFI_EVENT                    Event
+  );
+
+///
+/// The EFI_IP4_CONFIG2_PROTOCOL is designed to be the central repository for the common
+/// configurations and the administrator configurable settings for the EFI IPv4 network stack.
+/// An EFI IPv4 Configuration II Protocol instance will be installed on each communication device that
+/// the EFI IPv4 network stack runs on.
+///
+struct _EFI_IP4_CONFIG2_PROTOCOL {
+  EFI_IP4_CONFIG2_SET_DATA           SetData;
+  EFI_IP4_CONFIG2_GET_DATA           GetData;
+  EFI_IP4_CONFIG2_REGISTER_NOTIFY    RegisterDataNotify;
+  EFI_IP4_CONFIG2_UNREGISTER_NOTIFY  UnregisterDataNotify;
+};
+
+#endif
diff --git a/include/Ip6Config.h b/include/Ip6Config.h
new file mode 100644
index 0000000..003e50e
--- /dev/null
+++ b/include/Ip6Config.h
@@ -0,0 +1,366 @@
+/** @file
+  This file provides a definition of the EFI IPv6 Configuration
+  Protocol.
+
+Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at<BR>
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef __EFI_IP6CONFIG_PROTOCOL_H__
+#define __EFI_IP6CONFIG_PROTOCOL_H__
+
+#include <efiip.h>
+
+#define EFI_IP6_CONFIG_PROTOCOL_GUID \
+  { \
+    0x937fe521, 0x95ae, 0x4d1a, {0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } \
+  }
+
+typedef struct _EFI_IP6_CONFIG_PROTOCOL EFI_IP6_CONFIG_PROTOCOL;
+
+///
+/// EFI_IP6_CONFIG_DATA_TYPE
+///
+typedef enum {
+  ///
+  /// The interface information of the communication
+  /// device this EFI IPv6 Configuration Protocol instance manages.
+  /// This type of data is read only.The corresponding Data is of type
+  /// EFI_IP6_CONFIG_INTERFACE_INFO.
+  ///
+  Ip6ConfigDataTypeInterfaceInfo,
+  ///
+  /// The alternative interface ID for the
+  /// communication device this EFI IPv6 Configuration Protocol
+  /// instance manages if the link local IPv6 address generated from
+  /// the interfaced ID based on the default source the EFI IPv6
+  /// Protocol uses is a duplicate address. The length of the interface
+  /// ID is 64 bit. The corresponding Data is of type
+  /// EFI_IP6_CONFIG_INTERFACE_ID.
+  ///
+  Ip6ConfigDataTypeAltInterfaceId,
+  ///
+  /// The general configuration policy for the EFI IPv6 network
+  /// stack running on the communication device this EFI IPv6
+  /// Configuration Protocol instance manages. The policy will affect
+  /// other configuration settings. The corresponding Data is of type
+  /// EFI_IP6_CONFIG_POLICY.
+  ///
+  Ip6ConfigDataTypePolicy,
+  ///
+  /// The number of consecutive
+  /// Neighbor Solicitation messages sent while performing Duplicate
+  /// Address Detection on a tentative address. A value of zero
+  /// indicates that Duplicate Address Detection will not be performed
+  /// on tentative addresses. The corresponding Data is of type
+  /// EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS.
+  ///
+  Ip6ConfigDataTypeDupAddrDetectTransmits,
+  ///
+  /// The station addresses set manually for the EFI
+  /// IPv6 network stack. It is only configurable when the policy is
+  /// Ip6ConfigPolicyManual. The corresponding Data is a
+  /// pointer to an array of EFI_IPv6_ADDRESS instances.
+  ///
+  Ip6ConfigDataTypeManualAddress,
+  ///
+  /// The gateway addresses set manually for the EFI IPv6
+  /// network stack running on the communication device this EFI
+  /// IPv6 Configuration Protocol manages. It is not configurable when
+  /// the policy is Ip6ConfigPolicyAutomatic. The gateway
+  /// addresses must be unicast IPv6 addresses. The corresponding
+  /// Data is a pointer to an array of EFI_IPv6_ADDRESS instances.
+  ///
+  Ip6ConfigDataTypeGateway,
+  ///
+  /// The DNS server list for the EFI IPv6 network stack
+  /// running on the communication device this EFI IPv6
+  /// Configuration Protocol manages. It is not configurable when the
+  /// policy is Ip6ConfigPolicyAutomatic.The DNS server
+  /// addresses must be unicast IPv6 addresses. The corresponding
+  /// Data is a pointer to an array of EFI_IPv6_ADDRESS instances.
+  ///
+  Ip6ConfigDataTypeDnsServer,
+  ///
+  /// The number of this enumeration memebers.
+  ///
+  Ip6ConfigDataTypeMaximum
+} EFI_IP6_CONFIG_DATA_TYPE;
+
+///
+/// EFI_IP6_CONFIG_INTERFACE_INFO
+/// describes the operational state of the interface this
+/// EFI IPv6 Configuration Protocol instance manages.
+///
+typedef struct {
+  ///
+  /// The name of the interface. It is a NULL-terminated string.
+  ///
+  CHAR16                Name[32];
+  ///
+  /// The interface type of the network interface.
+  ///
+  UINT8                 IfType;
+  ///
+  /// The size, in bytes, of the network interface's hardware address.
+  ///
+  UINT32                HwAddressSize;
+  ///
+  /// The hardware address for the network interface.
+  ///
+  EFI_MAC_ADDRESS       HwAddress;
+  ///
+  /// Number of EFI_IP6_ADDRESS_INFO structures pointed to by AddressInfo.
+  ///
+  UINT32                AddressInfoCount;
+  ///
+  /// Pointer to an array of EFI_IP6_ADDRESS_INFO instances
+  /// which contain the local IPv6 addresses and the corresponding
+  /// prefix length information. Set to NULL if AddressInfoCount
+  /// is zero.
+  ///
+  EFI_IP6_ADDRESS_INFO  *AddressInfo;
+  ///
+  /// Number of route table entries in the following RouteTable.
+  ///
+  UINT32                RouteCount;
+  ///
+  /// The route table of the IPv6 network stack runs on this interface.
+  /// Set to NULL if RouteCount is zero.
+  ///
+  EFI_IP6_ROUTE_TABLE   *RouteTable;
+} EFI_IP6_CONFIG_INTERFACE_INFO;
+
+///
+/// EFI_IP6_CONFIG_INTERFACE_ID
+/// describes the 64-bit interface ID.
+///
+typedef struct {
+  UINT8                 Id[8];
+} EFI_IP6_CONFIG_INTERFACE_ID;
+
+///
+/// EFI_IP6_CONFIG_POLICY
+/// defines the general configuration policy the EFI IPv6
+/// Configuration Protocol supports.
+///
+typedef enum {
+  ///
+  /// Under this policy, the IpI6ConfigDataTypeManualAddress,
+  /// Ip6ConfigDataTypeGateway and Ip6ConfigDataTypeDnsServer
+  /// configuration data are required to be set manually.
+  /// The EFI IPv6 Protocol will get all required configuration
+  /// such as address, prefix and gateway settings from the EFI
+  /// IPv6 Configuration protocol.
+  ///
+  Ip6ConfigPolicyManual,
+  ///
+  /// Under this policy, the IpI6ConfigDataTypeManualAddress,
+  /// Ip6ConfigDataTypeGateway and Ip6ConfigDataTypeDnsServer
+  /// configuration data are not allowed to set via SetData().
+  /// All of these configurations are retrieved from some auto
+  /// configuration mechanism.
+  /// The EFI IPv6 Protocol will use the IPv6 stateless address
+  /// autoconfiguration mechanism and/or the IPv6 stateful address
+  /// autoconfiguration mechanism described in the related RFCs to
+  /// get address and other configuration information
+  ///
+  Ip6ConfigPolicyAutomatic
+} EFI_IP6_CONFIG_POLICY;
+
+///
+/// EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS
+/// describes the number of consecutive Neighbor Solicitation messages sent
+/// while performing Duplicate Address Detection on a tentative address.
+/// The default value for a newly detected communication device is 1.
+///
+typedef struct {
+  UINT32    DupAddrDetectTransmits;  ///< The number of consecutive Neighbor Solicitation messages sent.
+} EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS;
+
+///
+/// EFI_IP6_CONFIG_MANUAL_ADDRESS
+/// is used to set the station address information for the EFI IPv6 network
+/// stack manually when the policy is Ip6ConfigPolicyManual.
+///
+typedef struct {
+  EFI_IPv6_ADDRESS      Address;       ///< The IPv6 unicast address.
+  BOOLEAN               IsAnycast;     ///< Set to TRUE if Address is anycast.
+  UINT8                 PrefixLength;  ///< The length, in bits, of the prefix associated with this Address.
+} EFI_IP6_CONFIG_MANUAL_ADDRESS;
+
+
+/**
+  Set the configuration for the EFI IPv6 network stack running on the communication
+  device this EFI IPv6 Configuration Protocol instance manages.
+
+  This function is used to set the configuration data of type DataType for the EFI
+  IPv6 network stack running on the communication device this EFI IPv6 Configuration
+  Protocol instance manages.
+
+  The DataSize is used to calculate the count of structure instances in the Data for
+  some DataType that multiple structure instances are allowed.
+
+  This function is always non-blocking. When setting some type of configuration data,
+  an asynchronous process is invoked to check the correctness of the data, such as
+  doing Duplicate Address Detection on the manually set local IPv6 addresses.
+  EFI_NOT_READY is returned immediately to indicate that such an asynchronous process
+  is invoked and the process is not finished yet. The caller willing to get the result
+  of the asynchronous process is required to call RegisterDataNotify() to register an
+  event on the specified configuration data. Once the event is signaled, the caller
+  can call GetData() to get back the configuration data in order to know the result.
+  For other types of configuration data that do not require an asynchronous configuration
+  process, the result of the operation is immediately returned.
+
+  @param[in]     This           Pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
+  @param[in]     DataType       The type of data to set.
+  @param[in]     DataSize       Size of the buffer pointed to by Data in bytes.
+  @param[in]     Data           The data buffer to set. The type of the data buffer is
+                                associated with the DataType.
+
+  @retval EFI_SUCCESS           The specified configuration data for the EFI IPv6
+                                network stack is set successfully.
+  @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
+                                - This is NULL.
+                                - Data is NULL.
+                                - One or more fields in Data do not match the requirement of the
+                                  data type indicated by DataType.
+  @retval EFI_WRITE_PROTECTED   The specified configuration data is read-only or the specified
+                                configuration data can not be set under the current policy
+  @retval EFI_ACCESS_DENIED     Another set operation on the specified configuration
+                                data is already in process.
+  @retval EFI_NOT_READY         An asynchronous process is invoked to set the specified
+                                configuration data and the process is not finished yet.
+  @retval EFI_BAD_BUFFER_SIZE   The DataSize does not match the size of the type
+                                indicated by DataType.
+  @retval EFI_UNSUPPORTED       This DataType is not supported.
+  @retval EFI_OUT_OF_RESOURCES  Required system resources could not be allocated.
+  @retval EFI_DEVICE_ERROR      An unexpected system error or network error occurred.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP6_CONFIG_SET_DATA)(
+  IN EFI_IP6_CONFIG_PROTOCOL    *This,
+  IN EFI_IP6_CONFIG_DATA_TYPE   DataType,
+  IN UINTN                      DataSize,
+  IN VOID                       *Data
+  );
+
+/**
+  Get the configuration data for the EFI IPv6 network stack running on the communication
+  device this EFI IPv6 Configuration Protocol instance manages.
+
+  This function returns the configuration data of type DataType for the EFI IPv6 network
+  stack running on the communication device this EFI IPv6 Configuration Protocol instance
+  manages.
+
+  The caller is responsible for allocating the buffer used to return the specified
+  configuration data and the required size will be returned to the caller if the size of
+  the buffer is too small.
+
+  EFI_NOT_READY is returned if the specified configuration data is not ready due to an
+  already in progress asynchronous configuration process. The caller can call RegisterDataNotify()
+  to register an event on the specified configuration data. Once the asynchronous configuration
+  process is finished, the event will be signaled and a subsequent GetData() call will return
+  the specified configuration data.
+
+  @param[in]     This           Pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
+  @param[in]     DataType       The type of data to get.
+  @param[in,out] DataSize       On input, in bytes, the size of Data. On output, in bytes, the
+                                size of buffer required to store the specified configuration data.
+  @param[in]     Data           The data buffer in which the configuration data is returned. The
+                                type of the data buffer is associated with the DataType.
+
+  @retval EFI_SUCCESS           The specified configuration data is got successfully.
+  @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
+                                - This is NULL.
+                                - DataSize is NULL.
+                                - Data is NULL if *DataSize is not zero.
+  @retval EFI_BUFFER_TOO_SMALL  The size of Data is too small for the specified configuration data
+                                and the required size is returned in DataSize.
+  @retval EFI_NOT_READY         The specified configuration data is not ready due to an already in
+                                progress asynchronous configuration process.
+  @retval EFI_NOT_FOUND         The specified configuration data is not found.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP6_CONFIG_GET_DATA)(
+  IN EFI_IP6_CONFIG_PROTOCOL    *This,
+  IN EFI_IP6_CONFIG_DATA_TYPE   DataType,
+  IN OUT UINTN                  *DataSize,
+  IN VOID                       *Data   OPTIONAL
+  );
+
+/**
+  Register an event that is to be signaled whenever a configuration process on the specified
+  configuration data is done.
+
+  This function registers an event that is to be signaled whenever a configuration process
+  on the specified configuration data is done. An event can be registered for different DataType
+  simultaneously and the caller is responsible for determining which type of configuration data
+  causes the signaling of the event in such case.
+
+  @param[in]     This           Pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
+  @param[in]     DataType       The type of data to unregister the event for.
+  @param[in]     Event          The event to register.
+
+  @retval EFI_SUCCESS           The notification event for the specified configuration data is
+                                registered.
+  @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
+  @retval EFI_UNSUPPORTED       The configuration data type specified by DataType is not
+                                supported.
+  @retval EFI_OUT_OF_RESOURCES  Required system resources could not be allocated.
+  @retval EFI_ACCESS_DENIED     The Event is already registered for the DataType.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP6_CONFIG_REGISTER_NOTIFY)(
+  IN EFI_IP6_CONFIG_PROTOCOL    *This,
+  IN EFI_IP6_CONFIG_DATA_TYPE   DataType,
+  IN EFI_EVENT                  Event
+  );
+
+/**
+  Remove a previously registered event for the specified configuration data.
+
+  This function removes a previously registered event for the specified configuration data.
+
+  @param[in]     This           Pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
+  @param[in]     DataType       The type of data to remove the previously registered event for.
+  @param[in]     Event          The event to unregister.
+
+  @retval EFI_SUCCESS           The event registered for the specified configuration data is removed.
+  @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
+  @retval EFI_NOT_FOUND         The Event has not been registered for the specified
+                                DataType.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP6_CONFIG_UNREGISTER_NOTIFY)(
+  IN EFI_IP6_CONFIG_PROTOCOL    *This,
+  IN EFI_IP6_CONFIG_DATA_TYPE   DataType,
+  IN EFI_EVENT                  Event
+  );
+
+///
+/// The EFI_IP6_CONFIG_PROTOCOL provides the mechanism to set and get various
+/// types of configurations for the EFI IPv6 network stack.
+///
+struct _EFI_IP6_CONFIG_PROTOCOL {
+  EFI_IP6_CONFIG_SET_DATA           SetData;
+  EFI_IP6_CONFIG_GET_DATA           GetData;
+  EFI_IP6_CONFIG_REGISTER_NOTIFY    RegisterDataNotify;
+  EFI_IP6_CONFIG_UNREGISTER_NOTIFY  UnregisterDataNotify;
+};
+
+#endif
-- 
2.7.1


From 06e5348c1de053a0a07583a83629b21561ec2caa Mon Sep 17 00:00:00 2001
From: Gary Ching-Pang Lin <glin@suse.com>
Date: Wed, 14 Oct 2015 17:04:10 +0800
Subject: [PATCH 3/3] Add the optional HTTPBoot support

This commit adds the basic support for HTTPBoot, i.e. to fetch
the next stage loader with the HTTP protocol.

It requires gnu-efi >= 3.0.3 to support the URI device path and
Ip4Config2 or Ip6Config protocol support in the UEFI implementation.

To build shim.efi with HTTPBoot support:
make ENABLE_HTTPBOOT=1 shim.efi

Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>
---
 Makefile   |   9 +
 httpboot.c | 774 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 httpboot.h |  41 ++++
 shim.c     |  12 +
 4 files changed, 836 insertions(+)
 create mode 100644 httpboot.c
 create mode 100644 httpboot.h

diff --git a/Makefile b/Makefile
index 2c3d554..f636500 100644
--- a/Makefile
+++ b/Makefile
@@ -38,6 +38,10 @@ ifneq ($(origin OVERRIDE_SECURITY_POLICY), undefined)
 	CFLAGS	+= -DOVERRIDE_SECURITY_POLICY
 endif
 
+ifneq ($(origin ENABLE_HTTPBOOT), undefined)
+	CFLAGS	+= -DENABLE_HTTPBOOT
+endif
+
 ifeq ($(ARCH),x86_64)
 	CFLAGS	+= -mno-mmx -mno-sse -mno-red-zone -nostdinc \
 		-maccumulate-outgoing-args \
@@ -75,6 +79,11 @@ MOK_SOURCES = MokManager.c shim.h include/console.h PasswordCrypt.c PasswordCryp
 FALLBACK_OBJS = fallback.o
 FALLBACK_SRCS = fallback.c
 
+ifneq ($(origin ENABLE_HTTPBOOT), undefined)
+	OBJS += httpboot.o
+	SOURCES += httpboot.c httpboot.h
+endif
+
 all: $(TARGET)
 
 shim.crt:
diff --git a/httpboot.c b/httpboot.c
new file mode 100644
index 0000000..ad01b8d
--- /dev/null
+++ b/httpboot.c
@@ -0,0 +1,774 @@
+/*
+ * Copyright 2015 SUSE LINUX GmbH <glin@suse.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Significant portions of this code are derived from Tianocore
+ * (http://tianocore.sf.net) and are Copyright 2009-2012 Intel
+ * Corporation.
+ */
+
+#include <efi.h>
+#include <efilib.h>
+#include "str.h"
+#include "Http.h"
+#include "Ip4Config2.h"
+#include "Ip6Config.h"
+
+extern UINT8 in_protocol;
+
+#define perror(fmt, ...) ({						\
+		UINTN __perror_ret = 0;					\
+		if (!in_protocol)					\
+			__perror_ret = Print((fmt), ##__VA_ARGS__);	\
+		__perror_ret;						\
+	})
+
+static UINTN
+ascii_to_int (CONST CHAR8 *str)
+{
+    UINTN u;
+    CHAR8 c;
+
+    // skip preceeding white space
+    while (*str && *str == ' ') {
+        str += 1;
+    }
+
+    // convert digits
+    u = 0;
+    while ((c = *(str++))) {
+        if (c >= '0' && c <= '9') {
+            u = (u * 10) + c - '0';
+        } else {
+            break;
+        }
+    }
+
+    return u;
+}
+
+static UINTN
+convert_http_status_code (EFI_HTTP_STATUS_CODE status_code)
+{
+	if (status_code >= HTTP_STATUS_100_CONTINUE &&
+	    status_code <  HTTP_STATUS_200_OK) {
+		return (status_code - HTTP_STATUS_100_CONTINUE + 100);
+	} else if (status_code >= HTTP_STATUS_200_OK &&
+		   status_code <  HTTP_STATUS_300_MULTIPLE_CHIOCES) {
+		return (status_code - HTTP_STATUS_200_OK + 200);
+	} else if (status_code >= HTTP_STATUS_300_MULTIPLE_CHIOCES &&
+		   status_code <  HTTP_STATUS_400_BAD_REQUEST) {
+		return (status_code - HTTP_STATUS_300_MULTIPLE_CHIOCES + 300);
+	} else if (status_code >= HTTP_STATUS_400_BAD_REQUEST &&
+		   status_code <  HTTP_STATUS_500_INTERNAL_SERVER_ERROR) {
+		return (status_code - HTTP_STATUS_400_BAD_REQUEST + 400);
+	} else if (status_code >= HTTP_STATUS_500_INTERNAL_SERVER_ERROR) {
+		return (status_code - HTTP_STATUS_500_INTERNAL_SERVER_ERROR + 500);
+	}
+
+	return 0;
+}
+
+static EFI_DEVICE_PATH *devpath;
+static EFI_MAC_ADDRESS mac_addr;
+static IPv4_DEVICE_PATH ip4_node;
+static IPv6_DEVICE_PATH ip6_node;
+static BOOLEAN is_ip6;
+static CHAR8 *uri;
+
+BOOLEAN
+find_httpboot (EFI_HANDLE device)
+{
+	EFI_DEVICE_PATH *unpacked;
+	EFI_DEVICE_PATH *Node;
+	EFI_DEVICE_PATH *NextNode;
+	MAC_ADDR_DEVICE_PATH *MacNode;
+	URI_DEVICE_PATH *UriNode;
+	UINTN uri_size;
+
+	if (!uri)
+		FreePool(uri);
+
+	devpath = DevicePathFromHandle(device);
+	if (!devpath) {
+		perror(L"Failed to get device path\n");
+		return FALSE;
+	}
+
+	unpacked = UnpackDevicePath(devpath);
+	if (!unpacked) {
+		perror(L"Failed to unpack device path\n");
+		return FALSE;
+	}
+	Node = unpacked;
+
+	/* Traverse the device path to find IPv4()/Uri() or IPv6()/Uri() */
+	while (!IsDevicePathEnd(Node)) {
+		/* Save the MAC node so we can match the net card later */
+		if (DevicePathType(Node) == MESSAGING_DEVICE_PATH &&
+		    DevicePathSubType(Node) == MSG_MAC_ADDR_DP) {
+			MacNode = (MAC_ADDR_DEVICE_PATH *)Node;
+			CopyMem(&mac_addr, &MacNode->MacAddress, sizeof(EFI_MAC_ADDRESS));
+		}
+
+		if (DevicePathType(Node) == MESSAGING_DEVICE_PATH &&
+		    (DevicePathSubType(Node) == MSG_IPv4_DP ||
+		     DevicePathSubType(Node) == MSG_IPv6_DP)) {
+			/* Save the IP node so we can set up the connection later */
+			if (DevicePathSubType(Node) == MSG_IPv6_DP) {
+				CopyMem(&ip6_node, Node, sizeof(IPv6_DEVICE_PATH));
+				is_ip6 = TRUE;
+			} else {
+				CopyMem(&ip4_node, Node, sizeof(IPv4_DEVICE_PATH));
+				is_ip6 = FALSE;
+			}
+
+			Node = NextDevicePathNode(Node);
+			NextNode = NextDevicePathNode(Node);
+			if (DevicePathType(Node) == MESSAGING_DEVICE_PATH &&
+			    DevicePathSubType(Node) == MSG_URI_DP &&
+			    IsDevicePathEnd(NextNode)) {
+				/* Save the current URI */
+				UriNode = (URI_DEVICE_PATH *)Node;
+				uri_size = strlena(UriNode->Uri);
+				uri = AllocatePool(uri_size + 1);
+				if (!uri) {
+					perror(L"Failed to allocate uri\n");
+					return FALSE;
+				}
+				CopyMem(uri, UriNode->Uri, uri_size + 1);
+				FreePool(unpacked);
+				return TRUE;
+			}
+		}
+		Node = NextDevicePathNode(Node);
+	}
+
+	FreePool(unpacked);
+	return FALSE;
+}
+
+static EFI_STATUS
+generate_next_uri (CONST CHAR8 *current_uri, CONST CHAR8 *next_loader,
+		   CHAR8 **uri)
+{
+	CONST CHAR8 *ptr;
+	UINTN next_len;
+	UINTN path_len = 0;
+	UINTN count = 0;
+
+	if (strncmpa(current_uri, (CHAR8 *)"http://", 7) == 0) {
+		ptr = current_uri + 7;
+		count += 7;
+	} else {
+		return EFI_INVALID_PARAMETER;
+	}
+
+	/* Extract the path */
+	next_len = strlena(next_loader);
+	while (*ptr != '\0') {
+		count++;
+		if (*ptr == '/')
+			path_len = count;
+		ptr++;
+	}
+
+	*uri = AllocatePool(sizeof(CHAR8) * (path_len + next_len + 1));
+	if (!*uri)
+		return EFI_OUT_OF_RESOURCES;
+
+	CopyMem(*uri, current_uri, path_len);
+	CopyMem(*uri + path_len, next_loader, next_len);
+	(*uri)[path_len + next_len] = '\0';
+
+	return EFI_SUCCESS;
+}
+
+static EFI_STATUS
+extract_hostname (CONST CHAR8 *url, CHAR8 **hostname)
+{
+	CONST CHAR8 *ptr, *start;
+	UINTN host_len = 0;
+
+	if (strncmpa(url, (CHAR8 *)"http://", 7) == 0)
+		start = url + 7;
+	else
+		return EFI_INVALID_PARAMETER;
+
+	ptr = start;
+	while (*ptr != '/' && *ptr != '\0') {
+		host_len++;
+		ptr++;
+	}
+
+	*hostname = AllocatePool(sizeof(CHAR8) * (host_len + 1));
+	if (!*hostname)
+		return EFI_OUT_OF_RESOURCES;
+
+	CopyMem(*hostname, start, host_len);
+	(*hostname)[host_len] = '\0';
+
+	return EFI_SUCCESS;
+}
+
+#define SAME_MAC_ADDR(a, b) (!CompareMem(a, b, sizeof(EFI_MAC_ADDRESS)))
+
+static EFI_HANDLE
+get_nic_handle (EFI_MAC_ADDRESS *mac)
+{
+	EFI_GUID http_binding_guid = EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID;
+	EFI_DEVICE_PATH *unpacked = NULL;
+	EFI_DEVICE_PATH *Node;
+	EFI_DEVICE_PATH *temp_path = NULL;
+	MAC_ADDR_DEVICE_PATH *MacNode;
+	EFI_HANDLE handle = NULL;
+	EFI_HANDLE *buffer;
+	UINTN NoHandles;
+	UINTN i;
+	EFI_STATUS status;
+
+	/* Get the list of handles that support the HTTP service binding
+	   protocol */
+	status = uefi_call_wrapper(BS->LocateHandleBuffer, 5,
+				   ByProtocol,
+				   &http_binding_guid,
+				   NULL,
+				   &NoHandles,
+				   &buffer);
+	if (EFI_ERROR(status))
+		return NULL;
+
+	for (i = 0; i < NoHandles; i++) {
+		temp_path = DevicePathFromHandle(buffer[i]);
+
+		/* Match the MAC address */
+		unpacked = UnpackDevicePath(temp_path);
+		if (!unpacked) {
+			perror(L"Failed to unpack device path\n");
+			continue;
+		}
+		Node = unpacked;
+		while (!IsDevicePathEnd(Node)) {
+			if (DevicePathType(Node) == MESSAGING_DEVICE_PATH &&
+			    DevicePathSubType(Node) == MSG_MAC_ADDR_DP) {
+				MacNode = (MAC_ADDR_DEVICE_PATH *)Node;
+				if (SAME_MAC_ADDR(mac, &MacNode->MacAddress)) {
+					handle = buffer[i];
+					goto out;
+				}
+			}
+			Node = NextDevicePathNode(Node);
+		}
+		FreePool(unpacked);
+		unpacked = NULL;
+	}
+
+out:
+	if (unpacked)
+		FreePool(unpacked);
+	FreePool(buffer);
+
+	return handle;
+}
+
+static BOOLEAN
+is_unspecified_addr (EFI_IPv6_ADDRESS ip6)
+{
+	UINT8 i;
+
+	for (i = 0; i<16; i++) {
+		if (ip6.Addr[i] != 0)
+			return FALSE;
+	}
+
+	return TRUE;
+}
+
+static EFI_STATUS
+set_ip6(EFI_HANDLE *nic, IPv6_DEVICE_PATH *ip6node)
+{
+	EFI_GUID ip6_config_guid = EFI_IP6_CONFIG_PROTOCOL_GUID;
+	EFI_IP6_CONFIG_PROTOCOL *ip6cfg;
+	EFI_IP6_CONFIG_MANUAL_ADDRESS ip6;
+	EFI_IPv6_ADDRESS gateway;
+	EFI_STATUS status;
+
+	status = uefi_call_wrapper(BS->HandleProtocol, 3,
+				   nic,
+				   &ip6_config_guid,
+				   (VOID **)&ip6cfg);
+	if (EFI_ERROR (status))
+		return status;
+
+	ip6.Address = ip6node->LocalIpAddress;
+	ip6.PrefixLength = ip6node->PrefixLength;
+	ip6.IsAnycast = FALSE;
+	status = uefi_call_wrapper(ip6cfg->SetData, 4,
+				   ip6cfg,
+				   Ip6ConfigDataTypeManualAddress,
+				   sizeof(ip6),
+				   &ip6);
+	if (EFI_ERROR (status))
+		return status;
+
+	gateway = ip6node->GatewayIpAddress;
+	if (is_unspecified_addr(gateway))
+		return EFI_SUCCESS;
+
+	status = uefi_call_wrapper(ip6cfg->SetData, 4,
+				   ip6cfg,
+				   Ip6ConfigDataTypeGateway,
+				   sizeof(gateway),
+				   &gateway);
+	if (EFI_ERROR (status))
+		return status;
+
+	return EFI_SUCCESS;
+}
+
+static EFI_STATUS
+set_ip4(EFI_HANDLE *nic, IPv4_DEVICE_PATH *ip4node)
+{
+	EFI_GUID ip4_config2_guid = EFI_IP4_CONFIG2_PROTOCOL_GUID;
+	EFI_IP4_CONFIG2_PROTOCOL *ip4cfg2;
+	EFI_IP4_CONFIG2_MANUAL_ADDRESS ip4;
+	EFI_IPv4_ADDRESS gateway;
+	EFI_STATUS status;
+
+	status = uefi_call_wrapper(BS->HandleProtocol, 3,
+				   nic,
+				   &ip4_config2_guid,
+				   (VOID **)&ip4cfg2);
+	if (EFI_ERROR (status))
+		return status;
+
+	ip4.Address = ip4node->LocalIpAddress;
+	ip4.SubnetMask = ip4node->SubnetMask;
+	status = uefi_call_wrapper(ip4cfg2->SetData, 4,
+				   ip4cfg2,
+				   Ip4Config2DataTypeManualAddress,
+				   sizeof(ip4),
+				   &ip4);
+	if (EFI_ERROR (status))
+		return status;
+
+	gateway = ip4node->GatewayIpAddress;
+	status = uefi_call_wrapper(ip4cfg2->SetData, 4,
+				   ip4cfg2,
+				   Ip4Config2DataTypeGateway,
+				   sizeof(gateway),
+				   &gateway);
+	if (EFI_ERROR (status))
+		return status;
+
+	return EFI_SUCCESS;
+}
+
+static VOID EFIAPI
+httpnotify (EFI_EVENT Event, VOID *Context)
+{
+	*((BOOLEAN *) Context) = TRUE;
+}
+
+static EFI_STATUS
+configure_http (EFI_HTTP_PROTOCOL *http, BOOLEAN is_ip6)
+{
+	EFI_HTTP_CONFIG_DATA http_mode;
+	EFI_HTTPv4_ACCESS_POINT ip4node;
+	EFI_HTTPv6_ACCESS_POINT ip6node;
+
+	/* Configure HTTP */
+	ZeroMem(&http_mode, sizeof(http_mode));
+	http_mode.HttpVersion = HttpVersion11;
+	/* use the default time out */
+	http_mode.TimeOutMillisec = 0;
+
+	if (!is_ip6) {
+		http_mode.LocalAddressIsIPv6 = FALSE;
+		ZeroMem(&ip4node, sizeof(ip4node));
+		ip4node.UseDefaultAddress = TRUE;
+		http_mode.AccessPoint.IPv4Node = &ip4node;
+	} else {
+		http_mode.LocalAddressIsIPv6 = TRUE;
+		ZeroMem(&ip6node, sizeof(ip6node));
+		http_mode.AccessPoint.IPv6Node = &ip6node;
+	}
+
+	return uefi_call_wrapper(http->Configure, 2, http, &http_mode);
+}
+
+static EFI_STATUS
+send_http_request (EFI_HTTP_PROTOCOL *http, CHAR8 *hostname, CHAR8 *uri)
+{
+	EFI_HTTP_TOKEN tx_token;
+	EFI_HTTP_MESSAGE tx_message;
+	EFI_HTTP_REQUEST_DATA request;
+	EFI_HTTP_HEADER headers[3];
+	BOOLEAN request_done;
+	CHAR16 *Url = NULL;
+	EFI_STATUS status;
+	EFI_STATUS event_status;
+
+	/* Convert the ascii string to the UCS2 string */
+	Url = PoolPrint(L"%a", uri);
+	if (!Url)
+		return EFI_OUT_OF_RESOURCES;
+
+	request.Method = HttpMethodGet;
+	request.Url = Url;
+
+	/* Prepare the HTTP headers */
+	headers[0].FieldName = (CHAR8 *)"Host";
+	headers[0].FieldValue = hostname;
+	headers[1].FieldName = (CHAR8 *)"Accept";
+	headers[1].FieldValue = (CHAR8 *)"*/*";
+	headers[2].FieldName = (CHAR8 *)"User-Agent";
+	headers[2].FieldValue = (CHAR8 *)"UefiHttpBoot/1.0";
+
+	tx_message.Data.Request = &request;
+	tx_message.HeaderCount = 3;
+	tx_message.Headers = headers;
+	tx_message.BodyLength = 0;
+	tx_message.Body = NULL;
+
+	tx_token.Status = EFI_NOT_READY;
+	tx_token.Message = &tx_message;
+	tx_token.Event = NULL;
+	request_done = FALSE;
+	status = uefi_call_wrapper(BS->CreateEvent, 5,
+				   EVT_NOTIFY_SIGNAL,
+				   TPL_NOTIFY,
+				   httpnotify,
+				   &request_done,
+				   &tx_token.Event);
+	if (EFI_ERROR(status)) {
+		perror(L"Failed to Create Event for HTTP request: %r\n", status);
+		goto no_event;
+	}
+
+	/* Send out the request */
+	status = uefi_call_wrapper(http->Request, 2, http, &tx_token);
+	if (EFI_ERROR(status)) {
+		perror(L"HTTP request failed: %r\n", status);
+		goto error;
+	}
+
+	/* Wait for the response */
+	while (!request_done)
+		uefi_call_wrapper(http->Poll, 1, http);
+
+	if (EFI_ERROR(tx_token.Status)) {
+		perror(L"HTTP request: %r\n", tx_token.Status);
+		status = tx_token.Status;
+	}
+
+error:
+	event_status = uefi_call_wrapper(BS->CloseEvent, 1, tx_token.Event);
+	if (EFI_ERROR(event_status)) {
+		perror(L"Failed to close Event for HTTP request: %r\n",
+		       event_status);
+	}
+
+no_event:
+	if (Url)
+		FreePool(Url);
+
+	return status;
+}
+
+static EFI_STATUS
+receive_http_response(EFI_HTTP_PROTOCOL *http, VOID **buffer, UINTN *buf_size)
+{
+	EFI_HTTP_TOKEN rx_token;
+	EFI_HTTP_MESSAGE rx_message;
+	EFI_HTTP_RESPONSE_DATA response;
+	EFI_HTTP_STATUS_CODE http_status;
+	BOOLEAN response_done;
+	UINTN i, downloaded;
+	CHAR8 rx_buffer[9216];
+	EFI_STATUS status;
+	EFI_STATUS event_status;
+
+	/* Initialize the rx message and buffer */
+	response.StatusCode = HTTP_STATUS_UNSUPPORTED_STATUS;
+	rx_message.Data.Response = &response;
+	rx_message.HeaderCount = 0;
+	rx_message.Headers = 0;
+	rx_message.BodyLength = sizeof(rx_buffer);
+	rx_message.Body = rx_buffer;
+
+	rx_token.Status = EFI_NOT_READY;
+	rx_token.Message = &rx_message;
+	rx_token.Event = NULL;
+	response_done = FALSE;
+	status = uefi_call_wrapper(BS->CreateEvent, 5,
+				   EVT_NOTIFY_SIGNAL,
+				   TPL_NOTIFY,
+				   httpnotify,
+				   &response_done,
+				   &rx_token.Event);
+	if (EFI_ERROR(status)) {
+		perror(L"Failed to Create Event for HTTP response: %r\n", status);
+		goto no_event;
+	}
+
+	/* Notify the firmware to receive the HTTP messages */
+	status = uefi_call_wrapper(http->Response, 2, http, &rx_token);
+	if (EFI_ERROR(status)) {
+		perror(L"HTTP response failed: %r\n", status);
+		goto error;
+	}
+
+	/* Wait for the response */
+	while (!response_done)
+		uefi_call_wrapper(http->Poll, 1, http);
+
+	if (EFI_ERROR(rx_token.Status)) {
+		perror(L"HTTP response: %r\n", rx_token.Status);
+		status = rx_token.Status;
+		goto error;
+	}
+
+	/* Check the HTTP status code */
+	http_status = rx_token.Message->Data.Response->StatusCode;
+	if (http_status != HTTP_STATUS_200_OK) {
+		perror(L"HTTP Status Code: %d\n",
+		       convert_http_status_code(http_status));
+		status = EFI_ABORTED;
+		goto error;
+	}
+
+	/* Check the length of the file */
+	for (i = 0; i < rx_message.HeaderCount; i++) {
+		if (!strcmpa(rx_message.Headers[i].FieldName, (CHAR8 *)"Content-Length")) {
+			*buf_size = ascii_to_int(rx_message.Headers[i].FieldValue);
+		}
+	}
+
+	if (*buf_size == 0) {
+		perror(L"Failed to get Content-Lenght\n");
+		goto error;
+	}
+
+	*buffer = AllocatePool(*buf_size);
+	if (!*buffer) {
+		perror(L"Failed to allocate new rx buffer\n");
+		goto error;
+	}
+
+	downloaded = rx_message.BodyLength;
+
+	CopyMem(*buffer, rx_buffer, downloaded);
+
+	/* Retreive the rest of the message */
+	while (downloaded < *buf_size) {
+		if (rx_message.Headers) {
+			FreePool(rx_message.Headers);
+		}
+		rx_message.Headers = NULL;
+		rx_message.HeaderCount = 0;
+		rx_message.Data.Response = NULL;
+		rx_message.BodyLength = sizeof(rx_buffer);
+		rx_message.Body = rx_buffer;
+
+		rx_token.Status = EFI_NOT_READY;
+		response_done = FALSE;
+
+		status = uefi_call_wrapper(http->Response, 2, http, &rx_token);
+		if (EFI_ERROR(status)) {
+			perror(L"HTTP response failed: %r\n", status);
+			goto error;
+		}
+
+		while (!response_done)
+			uefi_call_wrapper(http->Poll, 1, http);
+
+		if (EFI_ERROR(rx_token.Status)) {
+			perror(L"HTTP response: %r\n", rx_token.Status);
+			status = rx_token.Status;
+			goto error;
+		}
+
+		if (rx_message.BodyLength + downloaded > *buf_size) {
+			status = EFI_BAD_BUFFER_SIZE;
+			goto error;
+		}
+
+		CopyMem(*buffer + downloaded, rx_buffer, rx_message.BodyLength);
+
+		downloaded += rx_message.BodyLength;
+	}
+
+error:
+	event_status = uefi_call_wrapper(BS->CloseEvent, 1, rx_token.Event);
+	if (EFI_ERROR(event_status)) {
+		perror(L"Failed to close Event for HTTP response: %r\n",
+		       event_status);
+	}
+
+no_event:
+	if (EFI_ERROR(status) && *buffer)
+		FreePool(*buffer);
+
+	return status;
+}
+
+static EFI_STATUS
+http_fetch (EFI_HANDLE image, EFI_HANDLE device,
+	    CHAR8 *hostname, CHAR8 *uri, BOOLEAN is_ip6,
+	    VOID **buffer, UINTN *buf_size)
+{
+	EFI_GUID http_binding_guid = EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID;
+	EFI_GUID http_protocol_guid = EFI_HTTP_PROTOCOL_GUID;
+	EFI_SERVICE_BINDING *service;
+	EFI_HANDLE http_handle;
+	EFI_HTTP_PROTOCOL *http;
+	EFI_STATUS status;
+	EFI_STATUS child_status;
+
+	*buffer = NULL;
+	*buf_size = 0;
+
+	/* Open HTTP Service Binding Protocol */
+	status = uefi_call_wrapper(BS->OpenProtocol, 6, device,
+				   &http_binding_guid, (VOID **)&service,
+				   image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+	if (EFI_ERROR (status))
+		return status;
+
+	/* Create the ChildHandle from the Service Binding */
+	/* Set the handle to NULL to request a new handle */
+	http_handle = NULL;
+	status = uefi_call_wrapper(service->CreateChild, 2, service,
+				   &http_handle);
+	if (EFI_ERROR (status))
+		return status;
+
+	/* Get the http protocol */
+	status = uefi_call_wrapper(BS->HandleProtocol, 3, http_handle,
+				   &http_protocol_guid, (VOID **)&http);
+	if (EFI_ERROR (status)) {
+		perror(L"Failed to get http\n");
+		goto error;
+	}
+
+	status = configure_http(http, is_ip6);
+	if (EFI_ERROR (status)) {
+		perror(L"Failed to configure http: %r\n", status);
+		goto error;
+	}
+
+	status = send_http_request(http, hostname, uri);
+	if (EFI_ERROR(status)) {
+		perror(L"Failed to send HTTP request: %r\n", status);
+		goto error;
+	}
+
+	status = receive_http_response(http, buffer, buf_size);
+	if (EFI_ERROR(status)) {
+		perror(L"Failed to receive HTTP response: %r\n", status);
+		goto error;
+	}
+
+error:
+	child_status = uefi_call_wrapper(service->DestroyChild, 2, service,
+					 http_handle);
+
+	if (EFI_ERROR(status)) {
+		return status;
+	} else if (EFI_ERROR(child_status)) {
+		return child_status;
+	}
+
+	return EFI_SUCCESS;
+}
+
+EFI_STATUS
+httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINTN *buf_size)
+{
+	EFI_STATUS status;
+	EFI_HANDLE nic;
+	CHAR8 *next_loader = NULL;
+	CHAR8 *next_uri = NULL;
+	CHAR8 *hostname = NULL;
+
+	if (!uri)
+		return EFI_NOT_READY;
+
+	next_loader = translate_slashes(DEFAULT_LOADER_CHAR);
+
+	/* Create the URI for the next loader based on the original URI */
+	status = generate_next_uri(uri, next_loader, &next_uri);
+	if (EFI_ERROR (status)) {
+		perror(L"Next URI: %a, %r\n", next_uri, status);
+		goto error;
+	}
+
+	/* Extract the hostname (or IP) from URI */
+	status = extract_hostname(uri, &hostname);
+	if (EFI_ERROR (status)) {
+		perror(L"hostname: %a, %r\n", hostname, status);
+		goto error;
+	}
+
+	/* Get the handle that associates with the NIC we are using and
+	   also supports the HTTP service binding protocol */
+	nic = get_nic_handle(&mac_addr);
+	if (!nic) {
+		goto error;
+	}
+
+	/* UEFI stops DHCP after fetching the image and stores the related
+	   information in the device path node. We have to set up the
+	   connection on our own for the further operations. */
+	if (!is_ip6)
+		status = set_ip4(nic, &ip4_node);
+	else
+		status = set_ip6(nic, &ip6_node);
+	if (EFI_ERROR (status)) {
+		perror(L"Failed to set IP for HTTPBoot: %r\n", status);
+		goto error;
+	}
+
+	/* Use HTTP protocl to fetch the remote file */
+	status = http_fetch (image, nic, hostname, next_uri, is_ip6,
+			     buffer, buf_size);
+	if (EFI_ERROR (status)) {
+		perror(L"Failed to fetch image: %r\n", status);
+		goto error;
+	}
+
+error:
+	FreePool(uri);
+	uri = NULL;
+	if (next_uri)
+		FreePool(next_uri);
+	if (hostname)
+		FreePool(hostname);
+
+	return status;
+}
diff --git a/httpboot.h b/httpboot.h
new file mode 100644
index 0000000..79ee465
--- /dev/null
+++ b/httpboot.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2015 SUSE LINUX GmbH <glin@suse.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Significant portions of this code are derived from Tianocore
+ * (http://tianocore.sf.net) and are Copyright 2009-2012 Intel
+ * Corporation.
+ */
+
+#ifndef _HTTPBOOT_H_
+#define _HTTPBOOT_H_
+
+BOOLEAN find_httpboot (EFI_DEVICE_PATH *devpath);
+
+EFI_STATUS httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINTN *buf_size);
+
+#endif
diff --git a/shim.c b/shim.c
index c93d96d..0e42a7b 100644
--- a/shim.c
+++ b/shim.c
@@ -39,6 +39,7 @@
 #include "PeImage.h"
 #include "shim.h"
 #include "netboot.h"
+#include "httpboot.h"
 #include "shim_cert.h"
 #include "replacements.h"
 #include "ucs2.h"
@@ -1651,6 +1652,17 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath)
 		}
 		data = sourcebuffer;
 		datasize = sourcesize;
+#if  defined(ENABLE_HTTPBOOT)
+	} else if (find_httpboot(li->DeviceHandle)) {
+		efi_status = httpboot_fetch_buffer (image_handle, &sourcebuffer,
+						    &sourcesize);
+		if (efi_status != EFI_SUCCESS) {
+			perror(L"Unable to fetch HTTP image: %r\n", efi_status);
+			return efi_status;
+		}
+		data = sourcebuffer;
+		datasize = sourcesize;
+#endif
 	} else {
 		/*
 		 * Read the new executable off disk
-- 
2.7.1

openSUSE Build Service is sponsored by