Automatically determine prefix when netbooted on EFI

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-07-02 16:56:35 +02:00
parent 574618a2e9
commit cae730b452
8 changed files with 237 additions and 123 deletions

View file

@ -27,14 +27,14 @@ GRUB_MOD_LICENSE ("GPLv3+");
/* GUID. */
static grub_efi_guid_t net_io_guid = GRUB_EFI_SIMPLE_NETWORK_GUID;
static grub_efi_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID;
static grub_err_t
send_card_buffer (const struct grub_net_card *dev,
struct grub_net_buff *pack)
{
grub_efi_status_t st;
grub_efi_simple_network_t *net = dev->data;
grub_efi_simple_network_t *net = dev->efi_net;
st = efi_call_7 (net->transmit, net, 0, pack->tail - pack->data,
pack->data, NULL, NULL, NULL);
if (st != GRUB_EFI_SUCCESS)
@ -46,7 +46,7 @@ static grub_ssize_t
get_card_packet (const struct grub_net_card *dev,
struct grub_net_buff *nb)
{
grub_efi_simple_network_t *net = dev->data;
grub_efi_simple_network_t *net = dev->efi_net;
grub_err_t err;
grub_efi_status_t st;
grub_efi_uintn_t bufsize = 1500;
@ -139,21 +139,62 @@ grub_efinet_findcards (void)
grub_memcpy (card->default_address.mac,
net->mode->current_address,
sizeof (card->default_address.mac));
card->data = net;
card->efi_net = net;
card->efi_handle = *handle;
grub_net_card_register (card);
}
grub_free (handles);
}
static void
grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
char **path)
{
struct grub_net_card *card;
grub_efi_device_path_t *dp;
dp = grub_efi_get_device_path (hnd);
if (! dp)
return;
FOR_NET_CARDS (card)
{
grub_efi_device_path_t *cdp;
struct grub_efi_pxe *pxe;
struct grub_efi_pxe_mode *pxe_mode;
if (card->driver != &efidriver)
continue;
cdp = grub_efi_get_device_path (card->efi_handle);
if (! cdp)
continue;
if (grub_efi_compare_device_paths (dp, cdp) != 0)
continue;
pxe = grub_efi_open_protocol (hnd, &pxe_io_guid,
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (! pxe)
continue;
pxe_mode = pxe->mode;
grub_net_configure_by_dhcp_ack (card->name, card, 0,
(struct grub_net_bootp_packet *)
&pxe_mode->dhcp_ack,
sizeof (pxe_mode->dhcp_ack),
1, device, path);
return;
}
}
GRUB_MOD_INIT(efinet)
{
grub_efinet_findcards ();
grub_efi_net_config = grub_efi_net_config_real;
}
GRUB_MOD_FINI(ofnet)
{
struct grub_net_card *card;
grub_efi_net_config = 0;
FOR_NET_CARDS (card)
if (card->driver && !grub_strcmp (card->driver->name, "efinet"))
{

View file

@ -936,7 +936,8 @@ grub_net_configure_by_dhcp_ack (const char *name,
const struct grub_net_card *card,
grub_net_interface_flags_t flags,
const struct grub_net_bootp_packet *bp,
grub_size_t size)
grub_size_t size,
int is_def, char **device, char **path)
{
grub_net_network_level_address_t addr;
grub_net_link_level_address_t hwaddr;
@ -945,6 +946,11 @@ grub_net_configure_by_dhcp_ack (const char *name,
addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
addr.ipv4 = bp->your_ip;
if (device)
*device = 0;
if (path)
*path = 0;
grub_memcpy (hwaddr.mac, bp->mac_addr,
bp->hw_len < sizeof (hwaddr.mac) ? bp->hw_len
: sizeof (hwaddr.mac));
@ -975,26 +981,57 @@ grub_net_configure_by_dhcp_ack (const char *name,
if (size > OFFSET_OF (boot_file, bp))
set_env_limn_ro (name, "boot_file", (char *) bp->boot_file,
sizeof (bp->boot_file));
if (is_def)
default_server = 0;
if (size > OFFSET_OF (server_name, bp)
&& bp->server_name[0])
{
set_env_limn_ro (name, "dhcp_server_name", (char *) bp->server_name,
sizeof (bp->server_name));
if (!default_server)
if (is_def && !default_server)
{
default_server = grub_strdup (bp->server_name);
grub_errno = GRUB_ERR_NONE;
}
grub_print_error ();
}
if (device && !*device)
{
*device = grub_xasprintf ("tftp,%s", bp->server_name);
grub_print_error ();
}
}
if (!default_server)
if (is_def && !default_server)
{
default_server = grub_xasprintf ("%d.%d.%d.%d",
((grub_uint8_t *) &bp->server_ip)[0],
((grub_uint8_t *) &bp->server_ip)[1],
((grub_uint8_t *) &bp->server_ip)[2],
((grub_uint8_t *) &bp->server_ip)[3]);
grub_errno = GRUB_ERR_NONE;
}
grub_print_error ();
}
if (device && !*device)
{
*device = grub_xasprintf ("tftp,%d.%d.%d.%d",
((grub_uint8_t *) &bp->server_ip)[0],
((grub_uint8_t *) &bp->server_ip)[1],
((grub_uint8_t *) &bp->server_ip)[2],
((grub_uint8_t *) &bp->server_ip)[3]);
grub_print_error ();
}
if (size > OFFSET_OF (boot_file, bp) && path)
{
*path = grub_strndup (bp->boot_file, sizeof (bp->boot_file));
grub_print_error ();
if (*path)
{
char *slash;
slash = grub_strrchr (*path, '/');
if (slash)
*slash = 0;
else
**path = 0;
}
}
if (size > OFFSET_OF (vendor, bp))
parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp));
@ -1025,7 +1062,7 @@ grub_net_process_dhcp (struct grub_net_buff *nb,
}
grub_net_configure_by_dhcp_ack (name, card,
0, (const struct grub_net_bootp_packet *) nb->data,
(nb->tail - nb->data));
(nb->tail - nb->data), 0, 0, 0);
grub_free (name);
if (grub_errno)
grub_print_error ();