summaryrefslogtreecommitdiffstats
path: root/master/jmm/efi-sni-bis
diff options
context:
space:
mode:
Diffstat (limited to 'master/jmm/efi-sni-bis')
-rw-r--r--master/jmm/efi-sni-bis828
1 files changed, 828 insertions, 0 deletions
diff --git a/master/jmm/efi-sni-bis b/master/jmm/efi-sni-bis
new file mode 100644
index 0000000..d63ec90
--- /dev/null
+++ b/master/jmm/efi-sni-bis
@@ -0,0 +1,828 @@
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index 2cdcc7b..e297c4f 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -107,6 +107,7 @@ kernel = {
+ x86 = kern/i386/pit.c;
+
+ x86_efi = disk/efi/efidisk.c;
++ x86_efi = net/efi/efinet.c;
+ x86_efi = kern/efi/efi.c;
+ x86_efi = kern/efi/init.c;
+ x86_efi = kern/efi/mm.c;
+diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
+index a83bf2e..0c2a88c 100644
+--- a/grub-core/kern/efi/init.c
++++ b/grub-core/kern/efi/init.c
+@@ -20,6 +20,7 @@
+ #include <grub/efi/efi.h>
+ #include <grub/efi/console.h>
+ #include <grub/efi/disk.h>
++#include <grub/efi/net.h>
+ #include <grub/term.h>
+ #include <grub/misc.h>
+ #include <grub/env.h>
+@@ -102,6 +103,7 @@ grub_efi_init (void)
+ bind_all_drivers();
+
+ grub_efidisk_init ();
++ grub_efinet_init ();
+ }
+
+ void
+@@ -133,6 +135,11 @@ grub_efi_set_prefix (void)
+ if (image)
+ {
+ if (!device)
++ device = grub_efinet_get_device_name (image->device_handle);
++ /* If we net booted - hard code the prefix */
++ if (device && !path)
++ path = grub_strdup("/grub/");
++ if (!device)
+ device = grub_efidisk_get_device_name (image->device_handle);
+ else if (device[0] == ',' || !device[0])
+ {
+@@ -187,6 +194,7 @@ grub_efi_set_prefix (void)
+ void
+ grub_efi_fini (void)
+ {
++ grub_efinet_fini ();
+ grub_efidisk_fini ();
+ grub_console_fini ();
+ }
+diff --git a/grub-core/kern/i386/efi/init.c b/grub-core/kern/i386/efi/init.c
+index f73f828..fe6971c 100644
+--- a/grub-core/kern/i386/efi/init.c
++++ b/grub-core/kern/i386/efi/init.c
+@@ -30,8 +30,8 @@
+ void
+ grub_machine_init (void)
+ {
+- grub_efi_init ();
+ grub_tsc_init ();
++ grub_efi_init ();
+ }
+
+ void
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index 5dd5ada..0ec088e 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -225,7 +225,14 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ dp = grub_efi_get_device_path (dev_handle);
+ }
+
+- if (! dev->disk || ! dev_handle || ! dp)
++ if (dev->net)
++ {
++ dev_handle = grub_efinet_get_device_handle (dev->net);
++ if (dev_handle)
++ dp = grub_efi_get_device_path (dev_handle);
++ }
++
++ if ((! dev->disk && ! dev->net ) || ! dev_handle || ! dp)
+ {
+ grub_error (GRUB_ERR_BAD_DEVICE, "not a valid root device");
+ goto fail;
+diff --git a/grub-core/net/efi/efinet.c b/grub-core/net/efi/efinet.c
+new file mode 100644
+index 0000000..f26aec1
+--- /dev/null
++++ b/grub-core/net/efi/efinet.c
+@@ -0,0 +1,541 @@
++/* efinet.c - EFI network access using SNI. */
++/*
++ * GRUB -- GRand Unified Bootloader
++ * Copyright (C) 2007, 2008, 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/dl.h>
++#include <grub/net.h>
++#include <grub/mm.h>
++#include <grub/types.h>
++#include <grub/misc.h>
++#include <grub/err.h>
++#include <grub/term.h>
++#include <grub/efi/api.h>
++#include <grub/efi/efi.h>
++#include <grub/efi/net.h>
++#include <grub/time.h>
++
++
++static grub_err_t grub_efinet_start (struct grub_net *);
++
++static grub_ether_addr ether_broadcast =
++ { {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} };
++
++struct grub_sni_data
++{
++ grub_efi_handle_t handle;
++ grub_efi_device_path_t *device_path;
++ grub_efi_simple_network_t *sni;
++ struct grub_sni_data *next;
++};
++
++static grub_efi_guid_t sni_guid = GRUB_EFI_SIMPLE_NETWORK_PROTOCOL;
++
++static struct grub_sni_data *sni_devices;
++
++/* Return the device path node right before the end node. */
++static grub_efi_device_path_t *
++find_last_device_path (const grub_efi_device_path_t * dp)
++{
++ grub_efi_device_path_t *next, *p;
++
++ if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
++ return 0;
++
++ for (p = (grub_efi_device_path_t *) dp, next =
++ GRUB_EFI_NEXT_DEVICE_PATH (p); !GRUB_EFI_END_ENTIRE_DEVICE_PATH (next);
++ p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next))
++ ;
++
++ return p;
++}
++
++/* Compare device paths. */
++static int
++compare_device_paths (const grub_efi_device_path_t * dp1,
++ const grub_efi_device_path_t * dp2)
++{
++ if (!dp1 || !dp2)
++ /* Return non-zero. */
++ return 1;
++
++ while (1)
++ {
++ grub_efi_uint8_t type1, type2;
++ grub_efi_uint8_t subtype1, subtype2;
++ grub_efi_uint16_t len1, len2;
++ int ret;
++
++ type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1);
++ type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2);
++
++ if (type1 != type2)
++ return (int) type2 - (int) type1;
++
++ subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1);
++ subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2);
++
++ if (subtype1 != subtype2)
++ return (int) subtype1 - (int) subtype2;
++
++ len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1);
++ len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2);
++
++ if (len1 != len2)
++ return (int) len1 - (int) len2;
++
++ ret = grub_memcmp (dp1, dp2, len1);
++ if (ret != 0)
++ return ret;
++
++ if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1))
++ break;
++
++ dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1);
++ dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
++ }
++
++ return 0;
++}
++
++
++
++static void
++free_devices (struct grub_sni_data *devices)
++{
++ struct grub_sni_data *p, *q;
++
++ for (p = devices; p; p = q)
++ {
++ q = p->next;
++ grub_free (p);
++ }
++}
++
++
++/* Add a device into a list of devices in an ascending order. */
++static void
++add_device (struct grub_sni_data *d)
++{
++ struct grub_sni_data **p;
++
++
++ for (p = &sni_devices; *p; p = &((*p)->next))
++ {
++ int ret;
++
++ ret = compare_device_paths (find_last_device_path ((*p)->device_path),
++ find_last_device_path (d->device_path));
++ if (ret == 0)
++ ret = compare_device_paths ((*p)->device_path, d->device_path);
++ if (ret == 0)
++ return;
++ else if (ret > 0)
++ break;
++ }
++
++
++ d->next = (*p);
++ (*p) = d;
++}
++
++
++
++static void
++make_devices (void)
++{
++ grub_efi_uintn_t num_handles;
++ grub_efi_handle_t *handles;
++ grub_efi_handle_t *handle;
++
++ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &sni_guid,
++ 0, &num_handles);
++
++ if (!handles)
++ return;
++
++
++
++ for (handle = handles; num_handles--; handle++)
++ {
++ grub_efi_simple_network_t *sni;
++ grub_efi_device_path_t *dp;
++ struct grub_sni_data *d;
++
++
++ dp = grub_efi_get_device_path (*handle);
++
++ sni = grub_efi_open_protocol (*handle, &sni_guid,
++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++
++ if (!sni)
++ continue;
++
++
++ d = grub_malloc (sizeof (*d));
++ if (!d)
++ {
++ grub_free (handles);
++ return;
++ }
++
++ d->handle = *handle;
++ d->device_path = dp;
++ d->sni = sni;
++
++ add_device (d);
++
++ }
++
++
++ grub_free (handles);
++
++}
++static void
++enumerate_snis (void)
++{
++ make_devices ();
++}
++
++
++static int
++get_unit_number (const char *name)
++{
++ unsigned long unit;
++
++ if (name[0] != 's' || name[1] != 'n' || name[2] != 'i')
++ goto fail;
++
++ unit = grub_strtoul (name + 3, 0, 10);
++ if (grub_errno != GRUB_ERR_NONE)
++ goto fail;
++
++ return (int) unit;
++
++fail:
++ grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a sni");
++ return -1;
++}
++
++static struct grub_sni_data *
++get_device (int num)
++{
++ struct grub_sni_data *d;
++
++ for (d = sni_devices; d && num; d = d->next, num--);
++
++ if (num == 0)
++ return d;
++
++ return 0;
++}
++
++
++static int
++tx_worker (struct grub_net *net, const void *frame, int len)
++{
++ struct grub_sni_data *private = (struct grub_sni_data *) net->data;
++ grub_uint64_t current_time, tx_time;
++ void *buf = NULL;
++ grub_efi_status_t status;
++
++ static int need_bodge = 1;
++
++ /* GRR the beasty EFI on the 64bit macminis doesn't return */
++ /* addresses from sni->transmit in sni->get_status, so we have to bodge */
++ /* the obvious bodge of looking at tx_good_frames in ->statistics */
++ /* doesn't work as that call appears to be missing on macs, the alternative */
++ /* is to flush the transmit q before and return whenever any buffer is */
++ /* returned. */
++
++ /* Flush list of frames */
++ do
++ {
++ buf = NULL;
++ efi_call_3 (private->sni->get_status, private->sni, NULL,
++ (void **) &buf);
++ }
++ while (buf);
++
++
++ tx_time = grub_get_time_ms ();
++
++ status =
++ efi_call_7 (private->sni->transmit, private->sni, 0, len, frame, NULL,
++ NULL, NULL);
++
++ if (status == GRUB_EFI_NOT_READY)
++ return 0; /*Try again */
++
++ if (status != GRUB_EFI_SUCCESS)
++ {
++ grub_efinet_start (net); /*Reset the interface */
++ return 0; /*Try again */
++ }
++
++ do
++ {
++ current_time = grub_get_time_ms ();
++ buf = NULL;
++ status =
++ efi_call_3 (private->sni->get_status, private->sni, NULL,
++ (void **) &buf);
++
++ if (status != GRUB_EFI_SUCCESS)
++ continue;
++
++ if (buf == frame)
++ {
++ /*EFI did TRT we can return success */
++ need_bodge = 0;
++ return len;
++ }
++
++ if (need_bodge)
++ return len;
++
++ }
++ while ((current_time - tx_time) < 1000);
++
++ /*Tx timed out reset and try again */
++ grub_efinet_start (net); /*Reset the interface */
++ return 0; /*Try again */
++
++}
++
++
++
++static grub_err_t
++grub_efinet_open (const char *name, struct grub_net *net)
++{
++ int num;
++ struct grub_sni_data *d = NULL;
++
++
++ if (name)
++ {
++ num = get_unit_number (name);
++ if (num < 0)
++ return grub_errno;
++ net->name = grub_strdup (name);
++ }
++ else
++ {
++ num = 0;
++ net->name = grub_strdup ("sni0");
++ }
++
++ d = get_device (num);
++
++ if (!d)
++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such device");
++
++
++ grub_printf("DEVICE PATH to %s:",name);
++ grub_efi_print_device_path(d->device_path);
++ grub_printf("\n");
++
++//net->id=num;
++ net->data = d;
++
++ return GRUB_ERR_NONE;
++}
++
++
++static grub_err_t
++grub_efinet_start (struct grub_net *net)
++{
++ struct grub_sni_data *private = (struct grub_sni_data *) net->data;
++ grub_efi_status_t status;
++
++ int tries = 3;
++
++ efi_call_1 (private->sni->shutdown, private->sni);
++ status = efi_call_3 (private->sni->initialize, private->sni, 0, 0);
++
++
++#if 0
++ efi_call_1 (private->sni->shutdown, private->sni);
++ efi_call_1 (private->sni->stop, private->sni);
++#endif
++
++ do
++ {
++ status = efi_call_1 (private->sni->start, private->sni);
++ if (status != GRUB_EFI_SUCCESS)
++ {
++ efi_call_1 (private->sni->shutdown, private->sni);
++ efi_call_1 (private->sni->stop, private->sni);
++ }
++ }
++ while ((status != GRUB_EFI_SUCCESS) && (tries--));
++
++ if (status != GRUB_EFI_SUCCESS)
++ return -1;
++
++ status = efi_call_3 (private->sni->initialize, private->sni, 0, 0);
++ if (status != GRUB_EFI_SUCCESS)
++ goto fail;
++
++ status =
++ efi_call_6 (private->sni->receive_filters, private->sni,
++ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
++ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST, 0, 0, 0, NULL);
++ if (status != GRUB_EFI_SUCCESS)
++ goto fail;
++
++ if (private->sni->mode->state != grub_efi_simple_network_initialized)
++ goto fail;
++
++ if (private->sni->mode->hw_address_size != GRUB_ETH_ALEN)
++ goto fail;
++
++ grub_memcpy (&net->my_eth_addr, private->sni->mode->current_address,
++ GRUB_ETH_ALEN);
++
++ net->is_running++;
++
++ return 0;
++
++fail:
++
++ efi_call_1 (private->sni->shutdown, private->sni);
++ efi_call_1 (private->sni->stop, private->sni);
++ return -1;
++}
++
++static void
++grub_efinet_stop (struct grub_net *net)
++{
++ struct grub_sni_data *private = (struct grub_sni_data *) net->data;
++
++ efi_call_1 (private->sni->shutdown, private->sni);
++ efi_call_1 (private->sni->stop, private->sni);
++ net->is_running = 0;
++}
++
++
++static void
++grub_efinet_close (struct grub_net *net)
++{
++ grub_efinet_stop (net);
++ grub_free (net->name);
++}
++
++
++static grub_err_t
++grub_efinet_send (struct grub_net *net, const void *frame, int len)
++{
++ int tries = 3;
++ int ret;
++
++ if (len <= 0)
++ return -1;
++
++ do
++ {
++ ret = tx_worker (net, frame, len);
++ if (ret > 0)
++ break;
++ }
++ while (tries--);
++
++
++ /* vodoo here - efi seems to drop packets in the TxQ for a short */
++ /* while after sending a broadcast packet - god alone knows why */
++
++ if (!grub_memcmp (frame, &ether_broadcast, GRUB_ETH_ALEN))
++ {
++ efi_call_1 (grub_efi_system_table->boot_services->stall, 100000);
++ }
++
++ return (ret > 0) ? GRUB_ERR_NONE : GRUB_ERR_WRITE_ERROR;
++
++}
++
++
++static grub_err_t
++grub_efinet_recv (struct grub_net *net, void *frame, int *lenp)
++{
++ struct grub_sni_data *private = (struct grub_sni_data *) net->data;
++ grub_efi_status_t st;
++ grub_efi_uintn_t len = GRUB_ETH_FRAME_LEN;
++
++ st =
++ efi_call_7 (private->sni->receive, private->sni, NULL, &len, frame, NULL,
++ NULL, NULL);
++
++ *lenp = len;
++
++
++ if (st == GRUB_EFI_NOT_READY)
++ return GRUB_ERR_TIMEOUT;
++ else if (st != GRUB_EFI_SUCCESS)
++ return GRUB_ERR_READ_ERROR;
++
++
++ return GRUB_ERR_NONE;
++}
++
++static struct grub_net_dev sni_net_dev = {
++ .name = "sni",
++ .open = grub_efinet_open,
++ .start = grub_efinet_start,
++ .stop = grub_efinet_stop,
++ .close = grub_efinet_close,
++ .send = grub_efinet_send,
++ .recv = grub_efinet_recv,
++ .next = 0
++};
++
++grub_efi_handle_t
++grub_net_efinet_get_device_handle(struct grub_net *net)
++{
++ struct grub_sni_data *private = (struct grub_sni_data *) net->data;
++ return private->handle;
++}
++
++void
++grub_net_efinet_init (void)
++{
++ enumerate_snis ();
++ grub_net_dev_register (&sni_net_dev);
++}
++
++void
++grub_net_efinet_fini (void)
++{
++ grub_net_dev_unregister (&sni_net_dev);
++ free_devices (sni_devices);
++}
++
++char * grub_net_efinet_get_device_name(grub_efi_handle_t h)
++{
++ struct grub_sni_data *p;
++ int i=0;
++
++ while (p=get_device(i)) {
++ if (p && (p->handle == h)) {
++ char *ret=grub_malloc (10); //FIXME
++ grub_sprintf(ret,"sni%d",i);
++ return ret;
++ }
++ i++;
++ }
++
++ return NULL;
++}
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index db63eec..a965d60 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -232,6 +232,12 @@ enum
+ GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_ITCDRIFT = 8,
+ };
+
++#define GRUB_EFI_SIMPLE_NETWORK_PROTOCOL \
++ { 0xA19832B9, 0xAC25, 0x11D3, \
++ {0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D} \
++ }
++
++
+ /* Enumerations. */
+ enum grub_efi_timer_delay
+ {
+@@ -1254,6 +1260,138 @@ struct grub_efi_block_io
+ };
+ typedef struct grub_efi_block_io grub_efi_block_io_t;
+
++
++struct grub_efi_network_statistics {
++ grub_efi_uint64_t rx_total_frames;
++ grub_efi_uint64_t rx_good_frames;
++ grub_efi_uint64_t rx_undersize_frames;
++ grub_efi_uint64_t rx_oversize_frames;
++ grub_efi_uint64_t rx_dropped_frames;
++ grub_efi_uint64_t rx_unicast_frames;
++ grub_efi_uint64_t rx_broadcast_frames;
++ grub_efi_uint64_t rx_multicast_frames;
++ grub_efi_uint64_t rx_crc_error_frames;
++ grub_efi_uint64_t rx_total_bytes;
++
++ grub_efi_uint64_t tx_total_frames;
++ grub_efi_uint64_t tx_good_frames;
++ grub_efi_uint64_t tx_undersize_frames;
++ grub_efi_uint64_t tx_oversize_frames;
++ grub_efi_uint64_t tx_dropped_frames;
++ grub_efi_uint64_t tx_unicast_frames;
++ grub_efi_uint64_t tx_broadcast_frames;
++ grub_efi_uint64_t tx_multicast_frames;
++ grub_efi_uint64_t tx_crc_error_frames;
++ grub_efi_uint64_t tx_total_bytes;
++
++ grub_efi_uint64_t collisions;
++ grub_efi_uint64_t unsupported_protocol;
++};
++typedef struct grub_efi_network_statistics grub_efi_network_statistics_t;
++
++enum grub_efi_simple_network_state {
++ grub_efi_simple_network_stopped,
++ grub_efi_simple_network_started,
++ grub_efi_simple_network_initialized,
++ grub_efi_simple_network_max_state
++};
++typedef enum grub_efi_simple_network_state grub_efi_simple_network_state_t;
++
++#define GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST 0x01
++#define GRUB_EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST 0x02
++#define GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST 0x04
++#define GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS 0x08
++#define GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST 0x10
++
++
++#define GRUB_EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT 0x01
++#define GRUB_EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT 0x02
++#define GRUB_EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT 0x04
++#define GRUB_EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT 0x08
++
++#define GRUB_EFI_MAX_MCAST_FILTER_CNT 16
++struct grub_efi_simple_network_mode
++{
++ grub_efi_uint32_t state;
++ grub_efi_uint32_t hw_address_size;
++ grub_efi_uint32_t media_header_size;
++ grub_efi_uint32_t max_packet_size;
++ grub_efi_uint32_t nv_ram_size;
++ grub_efi_uint32_t nv_ram_access_size;
++ grub_efi_uint32_t receive_filter_mask;
++ grub_efi_uint32_t receive_filter_setting;
++ grub_efi_uint32_t max_mcast_filter_count;
++ grub_efi_uint32_t mcast_filter_count;
++ grub_efi_mac_address_t mcast_filter[GRUB_EFI_MAX_MCAST_FILTER_CNT];
++ grub_efi_mac_address_t current_address;
++ grub_efi_mac_address_t broadcast_address;
++ grub_efi_mac_address_t permanent_address;
++ grub_efi_uint8_t if_type;
++ grub_efi_boolean_t mac_address_changeable;
++ grub_efi_boolean_t multiple_tx_supported;
++ grub_efi_boolean_t media_present_supported;
++ grub_efi_boolean_t media_present;
++};
++typedef struct grub_efi_simple_network_mode grub_efi_simple_network_mode_t;
++
++
++struct grub_efi_simple_network
++{
++ grub_efi_uint64_t revision;
++ grub_efi_status_t (*start) (struct grub_efi_simple_network *this);
++ grub_efi_status_t (*stop) (struct grub_efi_simple_network *this);
++ grub_efi_status_t (*initialize) (struct grub_efi_simple_network *this,
++ grub_efi_uintn_t extra_rx_buffer_size,
++ grub_efi_uintn_t extra_tx_buffer_size);
++ grub_efi_status_t (*reset) (struct grub_efi_simple_network *this,
++ grub_efi_boolean_t extended_verification);
++ grub_efi_status_t (*shutdown) (struct grub_efi_simple_network *this);
++ grub_efi_status_t (*receive_filters) (struct grub_efi_simple_network *this,
++ grub_efi_uint32_t enable,
++ grub_efi_uint32_t disable,
++ grub_efi_boolean_t reset_mcast_filter,
++ grub_efi_uintn_t mcast_filter_count,
++ grub_efi_mac_address_t *mcast_filter);
++ grub_efi_status_t (*station_address) (struct grub_efi_simple_network *this,
++ grub_efi_boolean_t reset,
++ grub_efi_mac_address_t *new);
++ grub_efi_status_t (*statistics) (struct grub_efi_simple_network *this,
++ grub_efi_boolean_t reset,
++ grub_efi_uintn_t *statistics_size,
++ grub_efi_network_statistics_t *statistics_table);
++ grub_efi_status_t (*mcast_ip_to_mac) (struct grub_efi_simple_network *this,
++ grub_efi_boolean_t ipv6,
++ grub_efi_ip_address_t *ip,
++ grub_efi_mac_address_t *mac);
++ grub_efi_status_t (*nvdata) (struct grub_efi_simple_network *this,
++ grub_efi_boolean_t read_write,
++ grub_efi_uintn_t offset,
++ grub_efi_uintn_t buffer_size,
++ void *buffer);
++ grub_efi_status_t (*get_status) (struct grub_efi_simple_network *this,
++ grub_efi_uint32_t *interrupt_status,
++ void **tx_buf);
++ grub_efi_status_t (*transmit) (struct grub_efi_simple_network *this,
++ grub_efi_uintn_t header_size,
++ grub_efi_uintn_t buffer_size,
++ void *buffer,
++ grub_efi_mac_address_t *src_addr,
++ grub_efi_mac_address_t *dst_addr,
++ grub_efi_uint16_t *protocol);
++ grub_efi_status_t (*receive) (struct grub_efi_simple_network *this,
++ grub_efi_uintn_t *header_size,
++ grub_efi_uintn_t *buffer_size,
++ void *buffer,
++ grub_efi_mac_address_t *src_addr,
++ grub_efi_mac_address_t *dst_addr,
++ grub_efi_uint16_t *protocol);
++ grub_efi_status_t (*wait_for_packet) (grub_efi_event_t event);
++ grub_efi_simple_network_mode_t *mode;
++};
++typedef struct grub_efi_simple_network grub_efi_simple_network_t;
++
++
++
+ #if GRUB_TARGET_SIZEOF_VOID_P == 4
+
+ #define efi_call_0(func) func()
+diff --git a/include/grub/efi/net.h b/include/grub/efi/net.h
+new file mode 100644
+index 0000000..368eaab
+--- /dev/null
++++ b/include/grub/efi/net.h
+@@ -0,0 +1,33 @@
++/*
++ * GRUB -- GRand Unified Bootloader
++ * Copyright (C) 2006,2007 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_NET_HEADER
++#define GRUB_EFI_NET_HEADER 1
++
++#include <grub/efi/api.h>
++#include <grub/symbol.h>
++#include <grub/net.h>
++
++grub_efi_handle_t
++EXPORT_FUNC(grub_efinet_get_device_handle) (grub_net_t net);
++char *EXPORT_FUNC(grub_efinet_get_device_name) (grub_efi_handle_t *handle);
++
++void grub_efinet_init (void);
++void grub_efinet_fini (void);
++
++#endif /* ! GRUB_EFI_NET_HEADER */