/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2010,2011 Free Software Foundation, Inc.
*
* 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/>.
*/
GRUB_MOD_LICENSE ("GPLv3+");
#ifdef __sun__
#define WORKAROUND_BROKEN_INTEL_DRIVERS
#endif
/* GUID. */
static grub_err_t
struct grub_net_buff *pack)
{
if (! net)
if (st != GRUB_EFI_SUCCESS)
while (1)
{
if (st != GRUB_EFI_SUCCESS)
if (txbuf)
return GRUB_ERR_NONE;
if (limit_time < grub_get_time_ms ())
}
}
static struct grub_net_buff *
{
if (! net)
return NULL;
if (efinet_receive_delay > 0)
#endif
if (!nb)
return NULL;
/* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible
by 4. So that IP header is aligned on 4 bytes. */
if (!nb)
{
return NULL;
}
if (st == GRUB_EFI_BUFFER_TOO_SMALL)
{
if (!nb)
return NULL;
/* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible
by 4. So that IP header is aligned on 4 bytes. */
if (!nb)
{
return NULL;
}
}
if (st != GRUB_EFI_SUCCESS)
{
return NULL;
}
if (err)
{
return NULL;
}
return nb;
}
static void
{
if (net)
{
/* First we call shutdown(), then stop() */
if (st != GRUB_EFI_SUCCESS)
(long)st);
if (st != GRUB_EFI_SUCCESS)
(long)st);
if (st != GRUB_EFI_SUCCESS)
(long)st);
else
}
}
{
.name = "efinet",
.close = efinet_close,
.send = send_card_buffer,
};
static int
{
/* If the current set of filters on the NIC doesn't match what we
want (constained by the set of supported filters, of course),
set them up now. */
{
/* If we're not exclusive, OR-in the required filters, just
in case we're sharing the interface. Of course, this is
no guarantee that these will be respected when the other
consumer changes the flags, but this is the best we can
do for now. */
1, /* Reset multicast filters */
0, /* No multicast filters included */
0);
/* Check if setting the filters failed */
if (st != GRUB_EFI_SUCCESS ||
return -1;
}
return 0;
}
static void
grub_efinet_findcards (void)
{
int i = 0;
/* Find handles which support the disk io interface. */
0, &num_handles);
if (! handles)
return;
{
#endif
/* We cannot ask for the exclusive handle here, otherwise we'd
blow away pxe, who may be holding our cached ack that we'll
retrieve later */
if (! net)
/* This should not happen... Why? */
continue;
if (!pxe)
continue;
if (!pxe_mode->dhcp_ack_recvd)
continue;
#endif
continue;
continue;
continue;
#if !defined(MULTI_CARD_UNDI_BROKEN_WORKAROUND)
/* Set up receive filters here */
setup_filters(net, 0);
#endif
if (!card)
{
grub_print_error ();
return;
}
/* We only support one active NIC at a time */
break;
#endif
}
}
/*
* This function assumes that card->efi_net was already initialized to
* a protocol handle for SNP.
*/
static int
{
int exclusive;
/* Open the SNP exclusively, otherwise upper layer drivers such as MNP may
steal our packets before we've had a chance to see them. */
/* If we cannot get exclusive use of the NIC, print a warning, but
try to continue */
if (! net)
{
grub_printf("WARNING: Could not open efinet exclusively. Packet loss\n");
grub_printf(" May occur if there is contention with other UEFI\n");
grub_printf(" drivers (network I/O may be slower).\n");
exclusive = 0;
}
else
{
exclusive = 1;
/* Once we gain exclusive access, the SNP will probably be shut down.
reinitialize it here. */
return -1;
return -1;
return -1;
}
return -1;
return 0;
}
static void
char **path)
{
if (! dp)
return;
{
continue;
if (! cdp)
continue;
continue;
if (! pxe)
return;
(struct grub_net_bootp_packet *)
/* Fully initialize SNP by gaining exclusive access, if possible,
and setting up the receive filters properly. */
if (init_efinet(card) != 0)
grub_printf("Could not initialize the NIC via UEFI\n");
return;
}
}
static char *
const char *val)
{
unsigned long receive_delay;
if (! val)
return NULL;
return grub_strdup(val);
}
#endif
{
#endif
}
{
grub_register_variable_hook (DELAY_ENV_VAR, 0, 0);
#endif
}