I don't have EFI spec under my hand now. Can we get away with making it a default or at least for the case when no interface overrides mac address. Extra config to workaround firmware bugs is usually harmful
Le 5 nov. 2015 9:17 PM, "Josef Bacik" <
address@hidden> a écrit :
We have some hardware that doesn't honor
EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST properly so we aren't getting
RA's that are multicasted properly (our switches respond to solicitations with a
multicast rather than a unicast). I don't want to add this filtering by
default, so add a new command to allow a user to specify a multicast receive
filter. We use it like this
efinet_multicast_filter efinet0 33:33:0:0:0:1
to get ipv6 multicasts which allows us to receive the router advertisements.
Thanks,
Signed-off-by: Josef Bacik <address@hidden>
---
grub-core/kern/efi/efi.c | 12 ++++-----
grub-core/net/drivers/efi/efinet.c | 51 ++++++++++++++++++++++++++++++++++++++
grub-core/net/net.c | 43 ++++++++++++++++++++++++++++++++
include/grub/efi/api.h | 5 +++-
include/grub/net.h | 3 +++
5 files changed, 107 insertions(+), 7 deletions(-)
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index 2e77834..efc3d33 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -652,12 +652,12 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
grub_efi_mac_address_device_path_t *mac
= (grub_efi_mac_address_device_path_t *) dp;
grub_printf ("/MacAddr(%02x:%02x:%02x:%02x:%02x:%02x,%x)",
- (unsigned) mac->mac_address[0],
- (unsigned) mac->mac_address[1],
- (unsigned) mac->mac_address[2],
- (unsigned) mac->mac_address[3],
- (unsigned) mac->mac_address[4],
- (unsigned) mac->mac_address[5],
+ (unsigned) mac->mac_address.addr[0],
+ (unsigned) mac->mac_address.addr[1],
+ (unsigned) mac->mac_address.addr[2],
+ (unsigned) mac->mac_address.addr[3],
+ (unsigned) mac->mac_address.addr[4],
+ (unsigned) mac->mac_address.addr[5],
(unsigned) mac->if_type);
}
break;
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
index c8f80a1..8c2c4f8 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -23,6 +23,7 @@
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
#include <grub/i18n.h>
+#include <grub/command.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -451,9 +452,58 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
}
}
+static grub_err_t
+grub_cmd_multicast_filter (struct grub_command *cmd __attribute__ ((unused)),
+ int argc, char **args)
+{
+ struct grub_net_card *card;
+ grub_efi_simple_network_t *net;
+ grub_net_link_level_address_t hwaddr;
+ grub_efi_mac_address_t filter_mac[1];
+ grub_efi_status_t st;
+
+ if (argc != 2)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
+
+ FOR_NET_CARDS (card)
+ if (grub_strcmp (card->name, args[0]) == 0)
+ break;
+
+ if (card == NULL)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found"));
+ if (card->driver != &efidriver)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not an efi card"));
+
+ if (grub_net_str_to_hwaddr (args[1], &hwaddr) == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("couldn't parse hw address"));
+ grub_memset (filter_mac, 0, sizeof(filter_mac));
+ grub_memcpy (filter_mac, hwaddr.mac, 6);
+
+ net = card->efi_net;
+ if (!(net->mode->receive_filter_mask &
+ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST))
+ return grub_error (GRUB_ERR_IO,
+ N_("device doesn't support multicast filtering"));
+
+ st = efi_call_6 (net->receive_filters, net,
+ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST, 0, 0, 1,
+ filter_mac);
+ if (st != GRUB_EFI_SUCCESS)
+ return grub_error (GRUB_ERR_IO,
+ N_("could not set multicast filter address"));
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_command_t cmd_multicast_filter;
+
GRUB_MOD_INIT(efinet)
{
grub_efinet_findcards ();
+ cmd_multicast_filter = grub_register_command ("efinet_multicast_filter",
+ grub_cmd_multicast_filter,
+ N_("CARD HWADDRESS"),
+ N_("Add a multicast filter"));
grub_efi_net_config = grub_efi_net_config_real;
}
@@ -464,5 +514,6 @@ GRUB_MOD_FINI(efinet)
FOR_NET_CARDS_SAFE (card, next)
if (card->driver == &efidriver)
grub_net_card_unregister (card);
+ grub_unregister_command(cmd_multicast_filter);
}
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index 65bea28..3a69f63 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -480,6 +480,49 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
return 1;
}
+int
+grub_net_str_to_hwaddr (const char *val, grub_net_link_level_address_t *hwaddr)
+{
+ grub_uint8_t newmac[6];
+ const char *ptr = val;
+ int word;
+
+ if (ptr[0] == ':' && ptr[1] != ':')
+ return 0;
+ if (ptr[0] == ':')
+ ptr++;
+
+ for (word = 0; word < 6; word++)
+ {
+ unsigned long t;
+ if (*ptr == ':')
+ {
+ word--;
+ ptr++;
+ continue;
+ }
+ t = grub_strtoul (ptr, (char **) &ptr, 16);
+ if (grub_errno)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ break;
+ }
+ if (t & ~0xff)
+ return 0;
+ newmac[word] = t;
+ if (*ptr != ':')
+ break;
+ ptr++;
+ }
+ if (*ptr != 0)
+ return grub_error (GRUB_ERR_NET_BAD_ADDRESS,
+ N_("unrecognized link level address '%s'"),
+ val);
+ hwaddr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+ grub_memcpy (hwaddr->mac, newmac, 6);
+ return 1;
+}
+
static int
match_net (const grub_net_network_level_netaddress_t *net,
const grub_net_network_level_address_t *addr)
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index 9a73976..48940be 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -523,7 +523,10 @@ typedef void *grub_efi_handle_t;
typedef void *grub_efi_event_t;
typedef grub_efi_uint64_t grub_efi_lba_t;
typedef grub_efi_uintn_t grub_efi_tpl_t;
-typedef grub_uint8_t grub_efi_mac_address_t[32];
+typedef struct {
+ grub_uint8_t addr[32];
+} grub_efi_mac_address_t;
+
typedef grub_uint8_t grub_efi_ipv4_address_t[4];
typedef grub_uint16_t grub_efi_ipv6_address_t[8];
typedef grub_uint8_t grub_efi_ip_address_t[8] __attribute__ ((aligned(4)));
diff --git a/include/grub/net.h b/include/grub/net.h
index a1ff519..12cc1db 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -522,6 +522,9 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target,
char *buf);
void
grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str);
+int
+grub_net_str_to_hwaddr (const char *val,
+ grub_net_link_level_address_t *hwaddr);
grub_err_t
grub_env_set_net_property (const char *intername, const char *suffix,
--
1.8.1
_______________________________________________
Grub-devel mailing list
address@hidden
https://lists.gnu.org/mailman/listinfo/grub-devel