[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC 1/2] net: add efihttp to do HTTP(S) Boot by UEFI HTTP Protocol
From: |
Ken Lin |
Subject: |
[RFC 1/2] net: add efihttp to do HTTP(S) Boot by UEFI HTTP Protocol |
Date: |
Fri, 20 Jan 2017 09:13:20 +0800 |
This patch implements HTTP Boot by using UEFI HTTP Protocols
defined in the UEFI spec (v2.5+):
28.6 EFI HTTP Protocols
It would be better to make efihttp as a single module similar to http.mod.
But I cannot fit my implementation to the interfaces (grub_net_app_protocol).
Some operations conflict: there is packets_pulled(), but no read().
So I placed efihttp in the net.mod.
It will be much appreciated to have suggestions of the best way
to get this patch integrated in grub.
Signed-off-by: Ken Lin <address@hidden>
Signed-off-by: Clay Chang <address@hidden>
Reviewed-by: Keng-Yu Lin <address@hidden>
---
grub-core/Makefile.core.def | 1 +
grub-core/net/bootp.c | 6 +
grub-core/net/drivers/efi/efihttp.c | 386 ++++++++++++++++++++++++++++++++++++
grub-core/net/drivers/efi/efinet.c | 1 +
grub-core/net/net.c | 36 +++-
include/grub/efi/api.h | 17 ++
include/grub/efi/http.h | 221 +++++++++++++++++++++
include/grub/err.h | 3 +-
include/grub/net.h | 1 +
9 files changed, 669 insertions(+), 3 deletions(-)
create mode 100755 grub-core/net/drivers/efi/efihttp.c
create mode 100755 include/grub/efi/http.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 2dfa22a..6a35951 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2143,6 +2143,7 @@ module = {
common = net/ethernet.c;
common = net/arp.c;
common = net/netbuff.c;
+ efi = net/drivers/efi/efihttp.c;
};
module = {
diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
index de9239c..17ac54c 100644
--- a/grub-core/net/bootp.c
+++ b/grub-core/net/bootp.c
@@ -26,6 +26,9 @@
#include <grub/datetime.h>
#include <grub/time.h>
#include <grub/list.h>
+#ifdef GRUB_MACHINE_EFI
+#include <grub/efi/http.h>
+#endif
static int
dissect_url (const char *url, char **proto, char **host, char **path)
@@ -339,6 +342,9 @@ grub_net_configure_by_dhcp_ack (const char *name,
}
else
grub_errno = GRUB_ERR_NONE;
+#ifdef GRUB_MACHINE_EFI
+ grub_efihttp_configure (card, bp);
+#endif
grub_free (proto);
grub_free (ip);
diff --git a/grub-core/net/drivers/efi/efihttp.c
b/grub-core/net/drivers/efi/efihttp.c
new file mode 100755
index 0000000..7e63f5c
--- /dev/null
+++ b/grub-core/net/drivers/efi/efihttp.c
@@ -0,0 +1,386 @@
+/* efihttp.c - EFI HTTP. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/misc.h>
+#include <grub/efi/efi.h>
+#include <grub/efi/api.h>
+#include <grub/efi/http.h>
+#include <grub/charset.h>
+
+/* EFI-HTTP(S) Boot variables */
+grub_efi_http_t *grub_efihttp = NULL;
+static grub_efi_boolean_t grub_efihttp_request_callback_done;
+static grub_efi_boolean_t grub_efihttp_response_callback_done;
+static grub_uint8_t *efihttp_rx_buf;
+
+static void
+grub_efihttp_request_callback (grub_efi_event_t event, void *context)
+{
+ grub_dprintf ("efihttp", "grub_efihttp_request_callback(), event:%p,
context:%p\n", event, context);
+ grub_efihttp_request_callback_done = 1;
+}
+
+static void
+grub_efihttp_response_callback (grub_efi_event_t event, void *context)
+{
+ grub_dprintf ("efihttp", "grub_efihttp_request_callback(), event:%p,
context:%p\n", event, context);
+ grub_efihttp_response_callback_done = 1;
+}
+
+grub_err_t
+grub_efihttp_configure (struct grub_net_card *card, const struct
grub_net_bootp_packet *bp)
+{
+ grub_efi_guid_t grub_efihttp_sb_guid =
GRUB_EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID;
+ grub_efi_guid_t grub_efihttp_guid = GRUB_EFI_HTTP_PROTOCOL_GUID;
+ grub_efi_service_binding_t *grub_efihttp_sb = NULL;
+ grub_efi_handle_t grub_efihttp_handle = NULL;
+ grub_efi_http_config_data_t grub_efihttp_config_data;
+ grub_efi_httpv4_access_point_t grub_efihttp_ipv4_node;
+ grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
+ grub_efi_status_t status;
+
+ grub_dprintf ("efihttp", "Enter grub_efihttp_configure()\n");
+
+ grub_efihttp_sb = grub_efi_open_protocol (card->efi_handle,
&grub_efihttp_sb_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (!grub_efihttp_sb)
+ {
+ grub_dprintf ("efihttp", "Fail to open the Service Binding protocol!\n");
+ return GRUB_ERR_EFI;
+ }
+
+ grub_dprintf ("efihttp", "sb->create_child()\n");
+ status = efi_call_2 (grub_efihttp_sb->create_child, grub_efihttp_sb,
&grub_efihttp_handle);
+ if (GRUB_EFI_SUCCESS != status)
+ {
+ grub_dprintf ("efihttp", "Fail to create child! status=%d\n",
(int)status);
+ return GRUB_ERR_EFI;
+ }
+
+ grub_dprintf ("efihttp", "b->handle_protocol()\n");
+ status = efi_call_3(b->handle_protocol, grub_efihttp_handle,
&grub_efihttp_guid, (void**)&grub_efihttp);
+ if (!grub_efihttp || GRUB_EFI_SUCCESS != status)
+ {
+ grub_dprintf ("efihttp", "Error! Fail to get HTTP protocol!
status=%d\n", (int)status);
+ return GRUB_ERR_EFI;
+ }
+
+ grub_memset (&grub_efihttp_config_data, 0, sizeof(grub_efihttp_config_data));
+ grub_efihttp_config_data.http_version = GRUB_EFI_HTTPVERSION11;
+ grub_efihttp_config_data.timeout_millisec = 5000;
+ grub_efihttp_config_data.local_address_is_ipv6 = 0;
+ grub_memset (&grub_efihttp_ipv4_node, 0, sizeof(grub_efihttp_ipv4_node));
+ grub_efihttp_ipv4_node.use_default_address = 0;
+ grub_memcpy ((void*)grub_efihttp_ipv4_node.local_address, &bp->your_ip,
sizeof (bp->your_ip));
+ grub_memcpy ((void*)grub_efihttp_ipv4_node.local_subnet, &bp->subnet_mask,
sizeof (bp->subnet_mask));
+ grub_efihttp_ipv4_node.local_port = 0;
+ grub_efihttp_config_data.access_point.ipv4_node = &grub_efihttp_ipv4_node;
+
+ grub_dprintf ("efihttp", "grub_efihttp->configure()\n");
+ status = efi_call_2 (grub_efihttp->configure, grub_efihttp,
&grub_efihttp_config_data);
+ if (GRUB_EFI_SUCCESS != status)
+ {
+ grub_dprintf ("efihttp", "Fail to do configuration! status=%d\n",
(int)status);
+ return GRUB_ERR_EFI;
+ }
+
+ grub_dprintf ("efihttp", "Leave grub_efihttp_configure()\n");
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_efihttp_open (grub_file_t file, const char *filename)
+{
+ grub_efi_http_request_data_t request_data;
+ grub_efi_http_header_t request_headers[3];
+ grub_efi_http_message_t *request_message;
+ grub_efi_http_token_t *request_token;
+ grub_efi_http_response_data_t response_data;
+ grub_efi_http_message_t *response_message;
+ grub_efi_http_token_t *response_token;
+ grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
+ grub_efi_status_t status;
+ grub_efi_http_status_code_t http_status;
+ const char *http = "http://";
+ char *url;
+ grub_efi_char16_t *usc2_url;
+ grub_uint32_t url_len, usc2_url_len;
+ grub_uint32_t offset, length, i;
+
+ grub_dprintf ("efihttp", "Enter grub_efihttp_open(), file->name:%s\n",
file->name);
+ grub_dprintf ("efihttp", "grub_efihttp:%p, grub_efihttp->request:%p\n",
grub_efihttp, grub_efihttp->request);
+
+ /* init */
+ grub_memset (&request_data, 0, sizeof (grub_efi_http_request_data_t));
+ request_message = grub_zalloc (sizeof (grub_efi_http_message_t));
+ request_token = grub_zalloc (sizeof (grub_efi_http_token_t));
+ grub_memset (&response_data, 0, sizeof (grub_efi_http_response_data_t));
+ response_message = grub_zalloc (sizeof (grub_efi_http_message_t));
+ response_token = grub_zalloc (sizeof (grub_efi_http_token_t));
+
+ request_data.method = GRUB_EFI_HTTPMETHODGET;
+
+ /* url */
+ url_len = grub_strlen (http) + grub_strlen (file->device->net->server) +
grub_strlen (file->device->net->name);
+ url = grub_malloc ((url_len + 1) * sizeof (url[0]));
+ grub_memset (url, 0, url_len);
+ grub_strncpy (url, http, grub_strlen(http));
+ offset = grub_strlen (http);
+ grub_strncpy (url + offset, file->device->net->server, grub_strlen
(file->device->net->server));
+ offset += grub_strlen (file->device->net->server);
+ grub_strncpy (url + offset, file->device->net->name, grub_strlen
(file->device->net->name));
+ url[url_len] = 0;
+ grub_dprintf ("efihttp", "url:%s\n", url);
+ usc2_url_len = url_len * GRUB_MAX_UTF16_PER_UTF8;
+ usc2_url = grub_malloc ((usc2_url_len + 1) * sizeof (usc2_url[0]));
+ usc2_url_len = grub_utf8_to_utf16 (usc2_url, usc2_url_len, (grub_uint8_t
*)url, url_len, NULL); /* convert string format from ascii to usc2 */
+ usc2_url[usc2_url_len] = 0;
+ request_data.url = usc2_url;
+
+ /* headers */
+ request_headers[0].field_name = (grub_efi_char8_t*)"Host";
+ request_headers[0].field_value =
(grub_efi_char8_t*)file->device->net->server;
+ request_headers[1].field_name = (grub_efi_char8_t*)"Accept";
+ request_headers[1].field_value = (grub_efi_char8_t*)"*/*";
+ request_headers[2].field_name = (grub_efi_char8_t*)"User-Agent";
+ request_headers[2].field_value = (grub_efi_char8_t*)"UefiHttpBoot/1.0";
+
+ request_message->data.request = &request_data;
+ request_message->header_count = 3;
+ request_message->headers = request_headers;
+ request_message->body_length = 0;
+ request_message->body = NULL;
+
+ /* request token */
+ request_token->event = NULL;
+ request_token->status = GRUB_EFI_NOT_READY;
+ request_token->message = request_message;
+ grub_efihttp_request_callback_done = 0;
+ grub_dprintf ("efihttp", "b->create_event()\n");
+ status = efi_call_5 (b->create_event,
+ GRUB_EFI_EVT_NOTIFY_SIGNAL,
+ GRUB_EFI_TPL_CALLBACK,
+ grub_efihttp_request_callback,
+ NULL,
+ &request_token->event);
+ if (GRUB_EFI_SUCCESS != status)
+ {
+ grub_dprintf ("efihttp", "Fail to create an event! status=%d\n",
(int)status);
+ return status;
+ }
+
+ grub_dprintf ("efihttp", "grub_efihttp:%p, grub_efihttp->request:%p\n",
grub_efihttp, grub_efihttp->request);
+
+ /* make a HTTP request */
+ grub_dprintf ("efihttp", "Before grub_efihttp->request(), url:%s\n", url);
+ status = efi_call_2 (grub_efihttp->request, grub_efihttp, request_token);
+ grub_dprintf ("efihttp", "After grub_efihttp->request()\n");
+ if (GRUB_EFI_SUCCESS != status)
+ {
+ grub_dprintf ("efihttp", "Fail to send a request! status=%d\n",
(int)status);
+ return GRUB_ERR_EFI;
+ }
+ /* allow the network stack 10 seconds to send the request successfully */
+ while (!grub_efihttp_request_callback_done)
+ {
+ efi_call_1(grub_efihttp->poll, grub_efihttp); // give the http driver
more motivation
+ }
+
+ response_data.status_code = GRUB_EFI_HTTP_STATUS_UNSUPPORTED_STATUS;
+ response_message->data.response = &response_data;
+ response_message->header_count = 0; // herader_count will be updated by the
HTTP driver on response
+ response_message->headers = NULL; // headers will be populated by the driver
on response
+ /* use zero BodyLength to only receive the response headers */
+ response_message->body_length = 0;
+ response_message->body = NULL;
+ response_token->event = NULL;
+ efi_call_5 (b->create_event,
+ GRUB_EFI_EVT_NOTIFY_SIGNAL,
+ GRUB_EFI_TPL_CALLBACK,
+ grub_efihttp_response_callback,
+ NULL,
+ &response_token->event);
+ response_token->status = GRUB_EFI_SUCCESS;
+ response_token->message = response_message;
+
+ /* wait for HTTP response */
+ grub_efihttp_response_callback_done = 0;
+ grub_dprintf ("efihttp", "Before grub_efihttp->response()\n");
+ status = efi_call_2 (grub_efihttp->response, grub_efihttp, response_token);
+ if (GRUB_EFI_SUCCESS != status)
+ {
+ grub_dprintf ("efihttp", "Fail to receive a response! status=%d\n",
(int)status);
+ return status;
+ }
+ while (!grub_efihttp_response_callback_done)
+ {
+ efi_call_1 (grub_efihttp->poll, grub_efihttp);
+ }
+ grub_dprintf ("efihttp", "After grub_efihttp->response(),
response_message->body_length:%d\n", response_message->body_length);
+
+ /* check the HTTP status code */
+ http_status = response_token->message->data.response->status_code;
+ grub_dprintf ("efihttp", "http_status=%d\n", (int)http_status);
+
+ /* parse the length of the file from the ContentLength header */
+ grub_dprintf ("efihttp", "response_message->header_count:%d\n",
response_message->header_count);
+ for (length = 0, i = 0; i < response_message->header_count; ++i)
+ {
+ if (!grub_strcmp((const char*)response_message->headers[i].field_name,
"Content-Length"))
+ {
+ length = grub_strtoul((const
char*)response_message->headers[i].field_value, 0, 10);
+ break;
+ }
+ }
+ file->size = (grub_off_t)length;
+
+ file->not_easily_seekable = 0;
+ file->data = (void*)filename;
+ file->device->net->offset = 0;
+ efihttp_rx_buf = grub_malloc (EFIHTTP_RX_BUF_LEN);
+
+ /* release */
+ grub_free (request_message);
+ grub_free (request_token);
+ grub_free (response_message);
+ grub_free (response_token);
+
+ grub_dprintf ("efihttp", "Leave grub_efihttp_open(), file->size:%d,
file->offset:%d\n", (int)file->size, (int)file->offset);
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_efihttp_close (grub_file_t file)
+{
+ grub_efi_status_t status;
+
+ grub_dprintf ("efihttp", "Enter grub_efihttp_close(),
file->device->net->name:%s, file->offset:%d\n", file->device->net->name,
(int)file->offset);
+ status = efi_call_2 (grub_efihttp->cancel, grub_efihttp, NULL);
+ if (GRUB_EFI_SUCCESS != status)
+ {
+ grub_dprintf ("efihttp", "Error! status=%d\n", (int)status);
+ return GRUB_ERR_EFI;
+ }
+ grub_free (efihttp_rx_buf);
+ file->offset = 0;
+ file->device->net->offset = 0;
+ grub_dprintf ("efihttp", "Leave grub_efihttp_close(),
file->device->net->name:%s, file->offset:%d\n", file->device->net->name,
(int)file->offset);
+
+ return GRUB_ERR_NONE;
+}
+
+grub_ssize_t
+grub_efihttp_read (grub_file_t file, char *buf, grub_size_t len)
+{
+ grub_efi_http_response_data_t response_data;
+ grub_efi_http_message_t *response_message;
+ grub_efi_http_token_t *response_token;
+ grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
+ grub_efi_status_t status;
+ grub_efi_http_status_code_t http_status;
+ char *ptr = buf;
+ grub_size_t amount, total = 0;
+
+ grub_dprintf ("efihttp", "Enter grub_efihttp_read(), len:%d\n", (int)len);
+
+ /* zero init */
+ grub_memset (&response_data, 0, sizeof (grub_efi_http_response_data_t));
+ response_message = grub_zalloc (sizeof (grub_efi_http_message_t));
+ response_token = grub_zalloc (sizeof (grub_efi_http_token_t));
+
+ /* receive the data */
+ response_message->data.response = &response_data;
+ response_message->header_count = 0; // herader_count will be updated by the
HTTP driver on response
+ response_message->headers = NULL; // headers will be populated by the driver
on response
+ response_message->body_length = EFIHTTP_RX_BUF_LEN;
+ response_message->body = efihttp_rx_buf;
+ response_token->event = NULL;
+ response_token->status = GRUB_EFI_NOT_READY;
+ response_token->message = response_message;
+ grub_efihttp_response_callback_done = 0;
+ efi_call_5 (b->create_event,
+ GRUB_EFI_EVT_NOTIFY_SIGNAL,
+ GRUB_EFI_TPL_CALLBACK,
+ grub_efihttp_response_callback,
+ NULL,
+ &response_token->event);
+
+ while (len > 0)
+ {
+ grub_dprintf ("efihttp", "file->device->net->offset:%d,
file->size:%d\n", (int)file->device->net->offset, (int)file->size);
+ amount = EFIHTTP_RX_BUF_LEN;
+ if (amount > len)
+ {
+ amount = len;
+ }
+
+ response_message->data.response = NULL;
+ if (!response_message->headers)
+ {
+ grub_free(response_message->headers);
+ }
+ response_message->header_count = 0;
+ response_message->headers = NULL;
+ response_message->body_length = amount;
+ grub_memset(efihttp_rx_buf, 0, amount);
+
+ /* accept another response */
+ response_token->status = GRUB_EFI_NOT_READY;
+ grub_efihttp_response_callback_done = 0; //false;
+ grub_dprintf ("efihttp", "Before grub_efihttp->response(),
response_message->body_length:%d\n", response_message->body_length);
+ status = efi_call_2 (grub_efihttp->response, grub_efihttp,
response_token);
+ if (GRUB_EFI_SUCCESS != status)
+ {
+ grub_dprintf ("efihttp", "Error! status=%d\n", (int)status);
+ return 0;
+ }
+
+ while (!grub_efihttp_response_callback_done)
+ {
+ efi_call_1(grub_efihttp->poll, grub_efihttp);
+ }
+
+ grub_dprintf ("efihttp", "After grub_efihttp->response(),
response_message->body_length:%d, response_token.status:%d\n",
+ response_message->body_length,
(int)response_token->status);
+
+ /* check the HTTP status code */
+ http_status = response_token->message->data.response->status_code;
+ grub_dprintf ("efihttp", "http_status=%d\n", (int)http_status);
+
+ len -= response_message->body_length;
+ total += response_message->body_length;
+ file->device->net->offset += response_message->body_length;
+ if (buf)
+ {
+ grub_memcpy (ptr, efihttp_rx_buf, response_message->body_length);
+ ptr += response_message->body_length;
+ }
+ grub_dprintf ("efihttp", "len:%d, total:%d,
file->device->net->offset:%d\n",
+ (int)len, (int)total, (int)file->device->net->offset);
+ }
+
+ /* release */
+ grub_free (response_message);
+ grub_free (response_token);
+
+ grub_dprintf ("efihttp", "Leave grub_efihttp_read(), file->offset:%d\n",
(int)file->offset);
+
+ return total;
+}
diff --git a/grub-core/net/drivers/efi/efinet.c
b/grub-core/net/drivers/efi/efinet.c
index 82a28fb..82b0fdd 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -518,6 +518,7 @@ grub_efinet_create_dhcp_ack_from_device_path
(grub_efi_device_path_t *dp, int *u
}
grub_memcpy (bp->boot_file, uri_dp->uri, uri_len);
grub_memcpy (&bp->your_ip, ipv4->local_ip_address, sizeof (bp->your_ip));
+ grub_memcpy (&bp->subnet_mask, ipv4->subnet_mask, sizeof
(bp->subnet_mask));
grub_memcpy (&bp->server_ip, ipv4->remote_ip_address, sizeof
(bp->server_ip));
bp->vendor[0] = GRUB_NET_BOOTP_RFC1048_MAGIC_0;
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index 2b329ee..90c5b48 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -32,6 +32,9 @@
#include <grub/loader.h>
#include <grub/bufio.h>
#include <grub/kernel.h>
+#ifdef GRUB_MACHINE_EFI
+#include <grub/efi/http.h>
+#endif
GRUB_MOD_LICENSE ("GPLv3+");
@@ -1504,7 +1507,12 @@ grub_net_fs_open (struct grub_file *file_out, const char
*name)
return grub_errno;
}
- err = file->device->net->protocol->open (file, name);
+#ifdef GRUB_MACHINE_EFI
+ if (grub_efihttp)
+ err = grub_efihttp_open (file, name);
+ else
+#endif
+ err = file->device->net->protocol->open (file, name);
if (err)
{
while (file->device->net->packs.first)
@@ -1543,7 +1551,12 @@ grub_net_fs_close (grub_file_t file)
grub_netbuff_free (file->device->net->packs.first->nb);
grub_net_remove_packet (file->device->net->packs.first);
}
- file->device->net->protocol->close (file);
+#ifdef GRUB_MACHINE_EFI
+ if (grub_efihttp)
+ grub_efihttp_close (file);
+ else
+#endif
+ file->device->net->protocol->close (file);
grub_free (file->device->net->name);
return GRUB_ERR_NONE;
}
@@ -1774,6 +1787,25 @@ grub_net_seek_real (struct grub_file *file, grub_off_t
offset)
static grub_ssize_t
grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
{
+#ifdef GRUB_MACHINE_EFI
+ if (grub_efihttp)
+ {
+ /* adjust the offset */
+ if (file->offset > file->device->net->offset)
+ {
+ grub_efihttp_read (file, NULL, (file->offset -
file->device->net->offset));
+ }
+ else if (file->offset < file->device->net->offset)
+ {
+ grub_efihttp_close (file);
+ grub_efihttp_open (file, file->device->net->name);
+ if (file->offset)
+ grub_efihttp_read (file, NULL, file->offset);
+ }
+
+ return grub_efihttp_read (file, buf, len);
+ }
+#endif
if (file->offset != file->device->net->offset)
{
grub_err_t err;
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index 99ba068..6a37eb9 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -982,6 +982,23 @@ struct grub_efi_bios_device_path
} GRUB_PACKED;
typedef struct grub_efi_bios_device_path grub_efi_bios_device_path_t;
+/* Service Binding definitions */
+struct grub_efi_service_binding;
+
+typedef grub_efi_status_t
+(*grub_efi_service_binding_create_child) (struct grub_efi_service_binding
*this,
+ grub_efi_handle_t *child_handle);
+
+typedef grub_efi_status_t
+(*grub_efi_service_binding_destroy_child) (struct grub_efi_service_binding
*this,
+ grub_efi_handle_t *child_handle);
+
+typedef struct grub_efi_service_binding
+{
+ grub_efi_service_binding_create_child create_child;
+ grub_efi_service_binding_destroy_child destroy_child;
+} grub_efi_service_binding_t;
+
struct grub_efi_open_protocol_information_entry
{
grub_efi_handle_t agent_handle;
diff --git a/include/grub/efi/http.h b/include/grub/efi/http.h
new file mode 100755
index 0000000..3a2725b
--- /dev/null
+++ b/include/grub/efi/http.h
@@ -0,0 +1,221 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_EFI_HTTP_HEADER
+#define GRUB_EFI_HTTP_HEADER 1
+
+#include <grub/symbol.h>
+#include <grub/net.h>
+#include <grub/efi/api.h>
+
+#define GRUB_EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID \
+ { 0xbdc8e6af, 0xd9bc, 0x4379, \
+ { 0xa7, 0x2a, 0xe0, 0xc4, 0xe7, 0x5d, 0xae, 0x1c } \
+ }
+
+#define GRUB_EFI_HTTP_PROTOCOL_GUID \
+ { 0x7A59B29B, 0x910B, 0x4171, \
+ { 0x82, 0x42, 0xA8, 0x5A, 0x0D, 0xF2, 0x5B, 0x5B } \
+ }
+
+#define EFIHTTP_WAIT_TIME 10000 // 10000ms = 10s
+#define EFIHTTP_RX_BUF_LEN 10240
+
+//******************************************
+// Protocol Interface Structure
+//******************************************
+struct grub_efi_http;
+
+//******************************************
+// EFI_HTTP_VERSION
+//******************************************
+typedef enum {
+ GRUB_EFI_HTTPVERSION10,
+ GRUB_EFI_HTTPVERSION11,
+ GRUB_EFI_HTTPVERSIONUNSUPPORTED
+} grub_efi_http_version_t;
+
+//******************************************
+// EFI_HTTPv4_ACCESS_POINT
+//******************************************
+typedef struct {
+ grub_efi_boolean_t use_default_address;
+ grub_efi_ipv4_address_t local_address;
+ grub_efi_ipv4_address_t local_subnet;
+ grub_efi_uint16_t local_port;
+} grub_efi_httpv4_access_point_t;
+
+//******************************************
+// EFI_HTTPv6_ACCESS_POINT
+//******************************************
+typedef struct {
+ grub_efi_ipv6_address_t local_address;
+ grub_efi_uint16_t local_port;
+} grub_efi_httpv6_access_point_t;
+
+//******************************************
+// EFI_HTTP_CONFIG_DATA
+//******************************************
+typedef struct {
+ grub_efi_http_version_t http_version;
+ grub_efi_uint32_t timeout_millisec;
+ grub_efi_boolean_t local_address_is_ipv6;
+ union {
+ grub_efi_httpv4_access_point_t *ipv4_node;
+ grub_efi_httpv6_access_point_t *ipv6_node;
+ } access_point;
+} grub_efi_http_config_data_t;
+
+//******************************************
+// EFI_HTTP_METHOD
+//******************************************
+typedef enum {
+ GRUB_EFI_HTTPMETHODGET,
+ GRUB_EFI_HTTPMETHODPOST,
+ GRUB_EFI_HTTPMETHODPATCH,
+ GRUB_EFI_HTTPMETHODOPTIONS,
+ GRUB_EFI_HTTPMETHODCONNECT,
+ GRUB_EFI_HTTPMETHODHEAD,
+ GRUB_EFI_HTTPMETHODPUT,
+ GRUB_EFI_HTTPMETHODDELETE,
+ GRUB_EFI_HTTPMETHODTRACE,
+} grub_efi_http_method_t;
+
+//******************************************
+// EFI_HTTP_REQUEST_DATA
+//******************************************
+typedef struct {
+ grub_efi_http_method_t method;
+ grub_efi_char16_t *url;
+} grub_efi_http_request_data_t;
+
+typedef enum {
+ GRUB_EFI_HTTP_STATUS_UNSUPPORTED_STATUS = 0,
+ GRUB_EFI_HTTP_STATUS_100_CONTINUE,
+ GRUB_EFI_HTTP_STATUS_101_SWITCHING_PROTOCOLS,
+ GRUB_EFI_HTTP_STATUS_200_OK,
+ GRUB_EFI_HTTP_STATUS_201_CREATED,
+ GRUB_EFI_HTTP_STATUS_202_ACCEPTED,
+ GRUB_EFI_HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION,
+ GRUB_EFI_HTTP_STATUS_204_NO_CONTENT,
+ GRUB_EFI_HTTP_STATUS_205_RESET_CONTENT,
+ GRUB_EFI_HTTP_STATUS_206_PARTIAL_CONTENT,
+ GRUB_EFI_HTTP_STATUS_300_MULTIPLE_CHIOCES,
+ GRUB_EFI_HTTP_STATUS_301_MOVED_PERMANENTLY,
+ GRUB_EFI_HTTP_STATUS_302_FOUND,
+ GRUB_EFI_HTTP_STATUS_303_SEE_OTHER,
+ GRUB_EFI_HTTP_STATUS_304_NOT_MODIFIED,
+ GRUB_EFI_HTTP_STATUS_305_USE_PROXY,
+ GRUB_EFI_HTTP_STATUS_307_TEMPORARY_REDIRECT,
+ GRUB_EFI_HTTP_STATUS_400_BAD_REQUEST,
+ GRUB_EFI_HTTP_STATUS_401_UNAUTHORIZED,
+ GRUB_EFI_HTTP_STATUS_402_PAYMENT_REQUIRED,
+ GRUB_EFI_HTTP_STATUS_403_FORBIDDEN,
+ GRUB_EFI_HTTP_STATUS_404_NOT_FOUND,
+ GRUB_EFI_HTTP_STATUS_405_METHOD_NOT_ALLOWED,
+ GRUB_EFI_HTTP_STATUS_406_NOT_ACCEPTABLE,
+ GRUB_EFI_HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED,
+ GRUB_EFI_HTTP_STATUS_408_REQUEST_TIME_OUT,
+ GRUB_EFI_HTTP_STATUS_409_CONFLICT,
+ GRUB_EFI_HTTP_STATUS_410_GONE,
+ GRUB_EFI_HTTP_STATUS_411_LENGTH_REQUIRED,
+ GRUB_EFI_HTTP_STATUS_412_PRECONDITION_FAILED,
+ GRUB_EFI_HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE,
+ GRUB_EFI_HTTP_STATUS_414_REQUEST_URI_TOO_LARGE,
+ GRUB_EFI_HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE,
+ GRUB_EFI_HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED,
+ GRUB_EFI_HTTP_STATUS_417_EXPECTATION_FAILED,
+ GRUB_EFI_HTTP_STATUS_500_INTERNAL_SERVER_ERROR,
+ GRUB_EFI_HTTP_STATUS_501_NOT_IMPLEMENTED,
+ GRUB_EFI_HTTP_STATUS_502_BAD_GATEWAY,
+ GRUB_EFI_HTTP_STATUS_503_SERVICE_UNAVAILABLE,
+ GRUB_EFI_HTTP_STATUS_504_GATEWAY_TIME_OUT,
+ GRUB_EFI_HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED
+} grub_efi_http_status_code_t;
+
+//******************************************
+// EFI_HTTP_RESPONSE_DATA
+//******************************************
+typedef struct {
+ grub_efi_http_status_code_t status_code;
+} grub_efi_http_response_data_t;
+
+//******************************************
+// EFI_HTTP_HEADER
+//******************************************
+typedef struct {
+ grub_efi_char8_t *field_name;
+ grub_efi_char8_t *field_value;
+} grub_efi_http_header_t;
+
+//******************************************
+// EFI_HTTP_MESSAGE
+//******************************************
+typedef struct {
+ union {
+ grub_efi_http_request_data_t *request;
+ grub_efi_http_response_data_t *response;
+ } data;
+ grub_efi_uint32_t header_count;
+ grub_efi_http_header_t *headers;
+ grub_efi_uint32_t body_length;
+ void *body;
+} grub_efi_http_message_t;
+
+//******************************************
+// EFI_HTTP_TOKEN
+//******************************************
+typedef struct {
+ grub_efi_event_t event;
+ grub_efi_status_t status;
+ grub_efi_http_message_t *message;
+} grub_efi_http_token_t;
+
+struct grub_efi_http {
+ grub_efi_status_t
+ (*get_mode_data) (struct grub_efi_http *this,
+ grub_efi_http_config_data_t *http_config_data);
+
+ grub_efi_status_t
+ (*configure) (struct grub_efi_http *this,
+ grub_efi_http_config_data_t *http_config_data);
+
+ grub_efi_status_t
+ (*request) (struct grub_efi_http *this,
+ grub_efi_http_token_t *token);
+
+ grub_efi_status_t
+ (*cancel) (struct grub_efi_http *this,
+ grub_efi_http_token_t *token);
+
+ grub_efi_status_t
+ (*response) (struct grub_efi_http *this,
+ grub_efi_http_token_t *token);
+
+ grub_efi_status_t
+ (*poll) (struct grub_efi_http *this);
+};
+typedef struct grub_efi_http grub_efi_http_t;
+
+extern grub_efi_http_t *grub_efihttp;
+grub_err_t grub_efihttp_configure (struct grub_net_card *card, const struct
grub_net_bootp_packet *bp);
+grub_err_t grub_efihttp_open (grub_file_t file, const char *filename);
+grub_err_t grub_efihttp_close (grub_file_t file);
+grub_ssize_t grub_efihttp_read (grub_file_t file, char *buf, grub_size_t len);
+
+#endif /* !GRUB_EFI_HTTP_HEADER */
diff --git a/include/grub/err.h b/include/grub/err.h
index 1590c68..eb0fc0e 100644
--- a/include/grub/err.h
+++ b/include/grub/err.h
@@ -71,7 +71,8 @@ typedef enum
GRUB_ERR_NET_PACKET_TOO_BIG,
GRUB_ERR_NET_NO_DOMAIN,
GRUB_ERR_EOF,
- GRUB_ERR_BAD_SIGNATURE
+ GRUB_ERR_BAD_SIGNATURE,
+ GRUB_ERR_EFI
}
grub_err_t;
diff --git a/include/grub/net.h b/include/grub/net.h
index 67c801e..d175b8f 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -435,6 +435,7 @@ struct grub_net_bootp_packet
grub_uint16_t flags;
grub_uint32_t client_ip;
grub_uint32_t your_ip;
+ grub_uint32_t subnet_mask;
grub_uint32_t server_ip;
grub_uint32_t gateway_ip;
grub_net_bootp_mac_addr_t mac_addr;
--
2.7.4