Module Name: src Committed By: martin Date: Wed Apr 11 14:51:43 UTC 2018
Modified Files: src/sys/arch/i386/stand/efiboot [netbsd-8]: Makefile.efiboot boot.c conf.c devopen.c devopen.h efiboot.c efiboot.h efidisk.c Added Files: src/sys/arch/i386/stand/efiboot [netbsd-8]: dev_net.c efinet.c efinet.h efipxe.c Log Message: Pull up following revision(s) (requested by nonaka in ticket #739): sys/arch/i386/stand/efiboot/efinet.h: revision 1.1 sys/arch/i386/stand/efiboot/efinet.c: revision 1.1 sys/arch/i386/stand/efiboot/conf.c: revision 1.2 sys/arch/i386/stand/efiboot/devopen.c: revision 1.5 sys/arch/i386/stand/efiboot/efidisk.c: revision 1.6 sys/arch/i386/stand/efiboot/devopen.h: revision 1.3 sys/arch/i386/stand/efiboot/efipxe.c: revision 1.1 sys/arch/i386/stand/efiboot/efiboot.c: revision 1.7 sys/arch/i386/stand/efiboot/boot.c: revision 1.10 sys/arch/i386/stand/efiboot/efiboot.h: revision 1.8 sys/arch/i386/stand/efiboot/Makefile.efiboot: revision 1.12 sys/arch/i386/stand/efiboot/dev_net.c: revision 1.1 efiboot: Added network boot support. To generate a diff of this commit: cvs rdiff -u -r1.9.2.2 -r1.9.2.3 \ src/sys/arch/i386/stand/efiboot/Makefile.efiboot cvs rdiff -u -r1.5.2.4 -r1.5.2.5 src/sys/arch/i386/stand/efiboot/boot.c cvs rdiff -u -r1.1 -r1.1.12.1 src/sys/arch/i386/stand/efiboot/conf.c cvs rdiff -u -r0 -r1.1.2.2 src/sys/arch/i386/stand/efiboot/dev_net.c \ src/sys/arch/i386/stand/efiboot/efinet.c \ src/sys/arch/i386/stand/efiboot/efinet.h \ src/sys/arch/i386/stand/efiboot/efipxe.c cvs rdiff -u -r1.1.12.3 -r1.1.12.4 src/sys/arch/i386/stand/efiboot/devopen.c cvs rdiff -u -r1.1.12.1 -r1.1.12.2 src/sys/arch/i386/stand/efiboot/devopen.h cvs rdiff -u -r1.4.10.2 -r1.4.10.3 src/sys/arch/i386/stand/efiboot/efiboot.c cvs rdiff -u -r1.5.2.2 -r1.5.2.3 src/sys/arch/i386/stand/efiboot/efiboot.h cvs rdiff -u -r1.1.12.4 -r1.1.12.5 src/sys/arch/i386/stand/efiboot/efidisk.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/i386/stand/efiboot/Makefile.efiboot diff -u src/sys/arch/i386/stand/efiboot/Makefile.efiboot:1.9.2.2 src/sys/arch/i386/stand/efiboot/Makefile.efiboot:1.9.2.3 --- src/sys/arch/i386/stand/efiboot/Makefile.efiboot:1.9.2.2 Mon Apr 2 08:50:33 2018 +++ src/sys/arch/i386/stand/efiboot/Makefile.efiboot Wed Apr 11 14:51:43 2018 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile.efiboot,v 1.9.2.2 2018/04/02 08:50:33 martin Exp $ +# $NetBSD: Makefile.efiboot,v 1.9.2.3 2018/04/11 14:51:43 martin Exp $ S= ${.CURDIR}/../../../../.. @@ -8,12 +8,12 @@ NEWVERSWHAT?= "EFI Boot" AFLAGS.start.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} -SOURCES?= start.S conf.c devopen.c efiboot.c self_reloc.c -LIBI386SRCS= boot.c biosdisk.c bootinfo.c bootinfo_biosgeom.c -LIBI386SRCS+= bootmenu.c diskbuf.c exec.c menuutils.c -LIBI386SRCS+= panic.c parseutils.c pread.c -LIBI386SRCS+= efichar.c eficons.c efidelay.c efidev.c efidisk.c efidisk_ll.c -LIBI386SRCS+= efigetsecs.c efimemory.c +SOURCES= start.S boot.c conf.c devopen.c dev_net.c self_reloc.c panic.c +SOURCES+= efiboot.c efichar.c eficons.c efidelay.c efidev.c +SOURCES+= efidisk.c efidisk_ll.c efigetsecs.c efimemory.c +SOURCES+= efinet.c efipxe.c +LIBI386SRCS= biosdisk.c bootinfo.c bootinfo_biosgeom.c bootmenu.c +LIBI386SRCS+= diskbuf.c exec.c menuutils.c parseutils.c pread.c SRCS= ${SOURCES} ${EXTRA_SOURCES} ${LIBI386SRCS} PIE_CFLAGS= @@ -57,10 +57,22 @@ CPPFLAGS+= -DSUPPORT_CD9660 CPPFLAGS+= -D"devb2cdb(bno)=(bno)" CPPFLAGS+= -DSUPPORT_DOSFS CPPFLAGS+= -DSUPPORT_EXT2FS +CPPFLAGS+= -DSUPPORT_BOOTP +CPPFLAGS+= -DSUPPORT_DHCP +CPPFLAGS+= -DSUPPORT_NFS +#CPPFLAGS+= -DSUPPORT_TFTP CPPFLAGS+= -DPASS_BIOSGEOM CPPFLAGS+= -DBIOSDISK_DEFAULT_SECSIZE=2048 # for bootinfo_biosgeom.c CPPFLAGS+= -DLIBSA_ENABLE_LS_OP +#CPPFLAGS+= -DARP_DEBUG +#CPPFLAGS+= -DBOOTP_DEBUG +#CPPFLAGS+= -DNET_DEBUG +#CPPFLAGS+= -DNETIF_DEBUG +#CPPFLAGS+= -DNFS_DEBUG +#CPPFLAGS+= -DRARP_DEBUG +#CPPFLAGS+= -DRPC_DEBUG + EFIDIR= ${S}/external/bsd/gnu-efi/dist GNUEFIARCH?= ${MACHINE_CPU} CPPFLAGS+= -I${EFIDIR}/inc -I${EFIDIR}/inc/${GNUEFIARCH} @@ -69,12 +81,12 @@ CPPFLAGS+= -I${EFIDIR}/inc/protocol SAMISCCPPFLAGS+= -DLIBSA_PRINTF_LONGLONG_SUPPORT SAMISCCPPFLAGS+= -DLIBSA_PRINTF_WIDTH_SUPPORT SAMISCCPPFLAGS+= -D"cdb2devb(bno)=(bno)" -SAMISCMAKEFLAGS+= SA_USE_CREAD=yes # Read compressed kernels -SAMISCMAKEFLAGS+= SA_INCLUDE_NET=no # Netboot via TFTP, NFS ### find out what to use for libsa SA_AS= library SAMISCMAKEFLAGS+="SA_USE_LOADFILE=yes" +SAMISCMAKEFLAGS+="SA_USE_CREAD=yes" +SAMISCMAKEFLAGS+="SA_INCLUDE_NET=yes" SAMISCMAKEFLAGS+="SA_ENABLE_LS_OP=yes" .include "${S}/lib/libsa/Makefile.inc" LIBSA= ${SALIB} Index: src/sys/arch/i386/stand/efiboot/boot.c diff -u src/sys/arch/i386/stand/efiboot/boot.c:1.5.2.4 src/sys/arch/i386/stand/efiboot/boot.c:1.5.2.5 --- src/sys/arch/i386/stand/efiboot/boot.c:1.5.2.4 Wed Apr 4 16:34:39 2018 +++ src/sys/arch/i386/stand/efiboot/boot.c Wed Apr 11 14:51:43 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: boot.c,v 1.5.2.4 2018/04/04 16:34:39 martin Exp $ */ +/* $NetBSD: boot.c,v 1.5.2.5 2018/04/11 14:51:43 martin Exp $ */ /*- * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> @@ -182,6 +182,21 @@ parsebootfile(const char *fname, char ** } static char * +snprint_bootdev(char *buf, size_t bufsize, const char *devname, int unit, + int partition) +{ + static const char *no_partition_devs[] = { "esp", "net", "nfs", "tftp" }; + int i; + + for (i = 0; i < __arraycount(no_partition_devs); i++) + if (strcmp(devname, no_partition_devs[i]) == 0) + break; + snprintf(buf, bufsize, "%s%d%c", devname, unit, + i < __arraycount(no_partition_devs) ? '\0' : 'a' + partition); + return buf; +} + +static char * sprint_bootsel(const char *filename) { char *fsname, *devname; @@ -191,8 +206,8 @@ sprint_bootsel(const char *filename) if (parsebootfile(filename, &fsname, &devname, &unit, &partition, &file) == 0) { - snprintf(buf, sizeof(buf), "%s%d%c:%s", devname, unit, - 'a' + partition, file); + snprintf(buf, sizeof(buf), "%s:%s", snprint_bootdev(buf, + sizeof(buf), devname, unit, partition), file); return buf; } return "(invalid)"; @@ -276,7 +291,9 @@ boot(void) if (!(boot_params.bp_flags & X86_BP_FLAGS_NOBOOTCONF)) { #ifdef EFIBOOTCFG_FILENAME - int rv = parsebootconf(EFIBOOTCFG_FILENAME); + int rv = EINVAL; + if (efi_bootdp_type != BOOT_DEVICE_TYPE_NET) + rv = parsebootconf(EFIBOOTCFG_FILENAME); if (rv) #endif parsebootconf(BOOTCFG_FILENAME); @@ -421,13 +438,15 @@ void command_dev(char *arg) { static char savedevname[MAXDEVNAME + 1]; + char buf[80]; char *fsname, *devname; const char *file; /* dummy */ if (*arg == '\0') { efi_disk_show(); - printf("default %s%d%c\n", default_devname, default_unit, - 'a' + default_partition); + efi_net_show(); + printf("default %s\n", snprint_bootdev(buf, sizeof(buf), + default_devname, default_unit, default_partition)); return; } Index: src/sys/arch/i386/stand/efiboot/conf.c diff -u src/sys/arch/i386/stand/efiboot/conf.c:1.1 src/sys/arch/i386/stand/efiboot/conf.c:1.1.12.1 --- src/sys/arch/i386/stand/efiboot/conf.c:1.1 Tue Jan 24 11:09:14 2017 +++ src/sys/arch/i386/stand/efiboot/conf.c Wed Apr 11 14:51:43 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: conf.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ +/* $NetBSD: conf.c,v 1.1.12.1 2018/04/11 14:51:43 martin Exp $ */ /* * Copyright (c) 1997 @@ -43,15 +43,52 @@ #ifdef SUPPORT_CD9660 #include <lib/libsa/cd9660.h> #endif +#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP) +#include <lib/libsa/net.h> +#include <lib/libsa/dev_net.h> +#ifdef SUPPORT_NFS +#include <lib/libsa/nfs.h> +#endif +#ifdef SUPPORT_TFTP +#include <lib/libsa/tftp.h> +#endif +#endif #include <biosdisk.h> +#include "efinet.h" struct devsw devsw[] = { { "disk", biosdisk_strategy, biosdisk_open, biosdisk_close, biosdisk_ioctl }, + { "net", net_strategy, net_open, net_close, net_ioctl }, }; int ndevs = __arraycount(devsw); +#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP) +struct netif_driver *netif_drivers[] = { + &efinetif, +}; +int n_netif_drivers = __arraycount(netif_drivers); +#endif + struct fs_ops file_system[] = { #ifdef SUPPORT_CD9660 + FS_OPS(null), +#endif + FS_OPS(null), FS_OPS(null), + FS_OPS(null), FS_OPS(null), +#ifdef SUPPORT_EXT2FS + FS_OPS(null), +#endif +#ifdef SUPPORT_MINIXFS3 + FS_OPS(null), +#endif +#ifdef SUPPORT_DOSFS + FS_OPS(null), +#endif +}; +int nfsys = __arraycount(file_system); + +struct fs_ops file_system_disk[] = { +#ifdef SUPPORT_CD9660 FS_OPS(cd9660), #endif FS_OPS(ffsv1), FS_OPS(ffsv2), @@ -66,4 +103,13 @@ struct fs_ops file_system[] = { FS_OPS(dosfs), #endif }; -int nfsys = __arraycount(file_system); +__CTASSERT(__arraycount(file_system) == __arraycount(file_system_disk)); +const int nfsys_disk = __arraycount(file_system_disk); + +struct fs_ops file_system_null = FS_OPS(null); +#ifdef SUPPORT_NFS +struct fs_ops file_system_nfs = FS_OPS(nfs); +#endif +#ifdef SUPPORT_TFTP +struct fs_ops file_system_tftp = FS_OPS(tftp); +#endif Index: src/sys/arch/i386/stand/efiboot/devopen.c diff -u src/sys/arch/i386/stand/efiboot/devopen.c:1.1.12.3 src/sys/arch/i386/stand/efiboot/devopen.c:1.1.12.4 --- src/sys/arch/i386/stand/efiboot/devopen.c:1.1.12.3 Wed Apr 4 16:34:39 2018 +++ src/sys/arch/i386/stand/efiboot/devopen.c Wed Apr 11 14:51:43 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: devopen.c,v 1.1.12.3 2018/04/04 16:34:39 martin Exp $ */ +/* $NetBSD: devopen.c,v 1.1.12.4 2018/04/11 14:51:43 martin Exp $ */ /*- * Copyright (c) 2005 The NetBSD Foundation, Inc. @@ -56,6 +56,8 @@ #include "efiboot.h" +#include <lib/libsa/dev_net.h> + #include <biosdisk.h> #include "devopen.h" #include <bootinfo.h> @@ -81,7 +83,14 @@ bios2dev(int biosdev, daddr_t sector, ch *unit = biosdev & 0x7f; - if (biosdev >= 0x80 + get_harddrives()) { + if (efi_bootdp_type == BOOT_DEVICE_TYPE_NET) { + *devname = "net"; + *unit = efi_net_get_booted_interface_unit(); + if (*unit < 0) + *unit = 0; + *partition = 0; + return; + } else if (biosdev >= 0x80 + get_harddrives()) { *devname = "cd"; *unit -= get_harddrives(); } else @@ -99,16 +108,90 @@ extern bool kernel_loaded; int devopen(struct open_file *f, const char *fname, char **file) { +#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP) + static const char *net_devnames[] = { +#if defined(SUPPORT_NFS) + "nfs", +#endif +#if defined(SUPPORT_TFTP) + "tftp", +#endif + }; +#endif + struct devdesc desc; + struct devsw *dev; char *fsname, *devname; int unit, partition; int biosdev; - int error; + int i, n, error; error = parsebootfile(fname, &fsname, &devname, &unit, &partition, (const char **) file); if (error) return error; + memcpy(file_system, file_system_disk, sizeof(*file_system) * nfsys); + nfsys = nfsys_disk; + +#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP) + for (i = 0; i < __arraycount(net_devnames); i++) { + if (strcmp(devname, net_devnames[i]) == 0) { + fsname = devname; + devname = "net"; + break; + } + } +#endif + + for (i = 1; i < ndevs; i++) { + dev = &devsw[i]; + if (strcmp(devname, DEV_NAME(dev)) == 0) { + if (strcmp(devname, "net") == 0) { + n = 0; +#if defined(SUPPORT_NFS) + if (strcmp(fsname, "nfs") == 0) { + memcpy(&file_system[n++], &file_system_nfs, + sizeof(file_system_nfs)); + } else +#endif +#if defined(SUPPORT_TFTP) + if (strcmp(fsname, "tftp") == 0) { + memcpy(&file_system[n++], &file_system_tftp, + sizeof(file_system_tftp)); + } else +#endif + { +#if defined(SUPPORT_NFS) + memcpy(&file_system[n++], &file_system_nfs, + sizeof(file_system_nfs)); +#endif +#if defined(SUPPORT_TFTP) + memcpy(&file_system[n++], &file_system_tftp, + sizeof(file_system_tftp)); +#endif + } + nfsys = n; + + try_bootp = 1; + } + + memset(&desc, 0, sizeof(desc)); + strlcpy(desc.d_name, devname, sizeof(desc.d_name)); + desc.d_unit = unit; + + f->f_dev = dev; + if (!kernel_loaded) { + strncpy(bibp.bootpath, *file, + sizeof(bibp.bootpath)); + BI_ADD(&bibp, BTINFO_BOOTPATH, sizeof(bibp)); + } + return DEV_OPEN(f->f_dev)(f, &desc); + } + } + + /* + * biosdisk + */ if (strcmp(devname, "esp") == 0) { bios2dev(boot_biosdev, boot_biossector, &devname, &unit, &partition); Index: src/sys/arch/i386/stand/efiboot/devopen.h diff -u src/sys/arch/i386/stand/efiboot/devopen.h:1.1.12.1 src/sys/arch/i386/stand/efiboot/devopen.h:1.1.12.2 --- src/sys/arch/i386/stand/efiboot/devopen.h:1.1.12.1 Wed Apr 4 16:34:39 2018 +++ src/sys/arch/i386/stand/efiboot/devopen.h Wed Apr 11 14:51:43 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: devopen.h,v 1.1.12.1 2018/04/04 16:34:39 martin Exp $ */ +/* $NetBSD: devopen.h,v 1.1.12.2 2018/04/11 14:51:43 martin Exp $ */ /*- * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> @@ -28,7 +28,17 @@ extern int boot_biosdev; extern daddr_t boot_biossector; +extern const int nfsys_disk; +extern struct fs_ops file_system_disk[]; +extern struct fs_ops file_system_nfs; +extern struct fs_ops file_system_tftp; +extern struct fs_ops file_system_null; #define MAXDEVNAME 16 void bios2dev(int, daddr_t, char **, int *, int *); + +struct devdesc { + char d_name[MAXDEVNAME]; + char d_unit; +}; Index: src/sys/arch/i386/stand/efiboot/efiboot.c diff -u src/sys/arch/i386/stand/efiboot/efiboot.c:1.4.10.2 src/sys/arch/i386/stand/efiboot/efiboot.c:1.4.10.3 --- src/sys/arch/i386/stand/efiboot/efiboot.c:1.4.10.2 Mon Apr 2 08:50:33 2018 +++ src/sys/arch/i386/stand/efiboot/efiboot.c Wed Apr 11 14:51:43 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: efiboot.c,v 1.4.10.2 2018/04/02 08:50:33 martin Exp $ */ +/* $NetBSD: efiboot.c,v 1.4.10.3 2018/04/11 14:51:43 martin Exp $ */ /*- * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> @@ -34,7 +34,7 @@ EFI_HANDLE IH; EFI_DEVICE_PATH *efi_bootdp; -int efi_bootdp_type = BIOSDISK_TYPE_HD; +enum efi_boot_device_type efi_bootdp_type = BOOT_DEVICE_TYPE_HD; EFI_LOADED_IMAGE *efi_li; uintptr_t efi_main_sp; physaddr_t efi_loadaddr, efi_kernel_start; @@ -79,12 +79,19 @@ efi_main(EFI_HANDLE imageHandle, EFI_SYS for (dp = dp0; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp)) { if (DevicePathType(dp) == MEDIA_DEVICE_PATH && DevicePathSubType(dp) == MEDIA_CDROM_DP) { - efi_bootdp_type = BIOSDISK_TYPE_CD; + efi_bootdp_type = BOOT_DEVICE_TYPE_CD; + break; + } + if (DevicePathType(dp) == MESSAGING_DEVICE_PATH && + DevicePathSubType(dp) == MSG_MAC_ADDR_DP) { + efi_bootdp_type = BOOT_DEVICE_TYPE_NET; break; } } efi_disk_probe(); + efi_pxe_probe(); + efi_net_probe(); status = uefi_call_wrapper(BS->SetWatchdogTimer, 4, 0, 0, 0, NULL); if (EFI_ERROR(status)) Index: src/sys/arch/i386/stand/efiboot/efiboot.h diff -u src/sys/arch/i386/stand/efiboot/efiboot.h:1.5.2.2 src/sys/arch/i386/stand/efiboot/efiboot.h:1.5.2.3 --- src/sys/arch/i386/stand/efiboot/efiboot.h:1.5.2.2 Mon Apr 2 08:50:33 2018 +++ src/sys/arch/i386/stand/efiboot/efiboot.h Wed Apr 11 14:51:43 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: efiboot.h,v 1.5.2.2 2018/04/02 08:50:33 martin Exp $ */ +/* $NetBSD: efiboot.h,v 1.5.2.3 2018/04/11 14:51:43 martin Exp $ */ /*- * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> @@ -46,7 +46,11 @@ void print_banner(void); /* efiboot.c */ extern EFI_HANDLE IH; extern EFI_DEVICE_PATH *efi_bootdp; -extern int efi_bootdp_type; +extern enum efi_boot_device_type { + BOOT_DEVICE_TYPE_HD, + BOOT_DEVICE_TYPE_CD, + BOOT_DEVICE_TYPE_NET +} efi_bootdp_type; extern EFI_LOADED_IMAGE *efi_li; extern uintptr_t efi_main_sp; extern physaddr_t efi_loadaddr, efi_kernel_start; @@ -80,5 +84,15 @@ void efi_memory_show_map(bool); EFI_MEMORY_DESCRIPTOR *efi_memory_get_map(UINTN *, UINTN *, UINTN *, UINT32 *, bool); +/* efinet.c */ +void efi_net_probe(void); +void efi_net_show(void); +int efi_net_get_booted_interface_unit(void); + +/* efipxe.c */ +void efi_pxe_probe(void); +void efi_pxe_show(void); +bool efi_pxe_match_booted_interface(const EFI_MAC_ADDRESS *, UINT32); + /* panic.c */ __dead VOID Panic(IN CHAR16 *, ...); Index: src/sys/arch/i386/stand/efiboot/efidisk.c diff -u src/sys/arch/i386/stand/efiboot/efidisk.c:1.1.12.4 src/sys/arch/i386/stand/efiboot/efidisk.c:1.1.12.5 --- src/sys/arch/i386/stand/efiboot/efidisk.c:1.1.12.4 Wed Apr 4 16:34:39 2018 +++ src/sys/arch/i386/stand/efiboot/efidisk.c Wed Apr 11 14:51:43 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: efidisk.c,v 1.1.12.4 2018/04/04 16:34:39 martin Exp $ */ +/* $NetBSD: efidisk.c,v 1.1.12.5 2018/04/11 14:51:43 martin Exp $ */ /*- * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> @@ -107,7 +107,7 @@ next: FreePool(handles); - if (efi_bootdp_type == BIOSDISK_TYPE_CD) { + if (efi_bootdp_type == BOOT_DEVICE_TYPE_CD) { edi = TAILQ_FIRST(&efi_disklist); if (edi != NULL && edi->bootdev) { edi->type = BIOSDISK_TYPE_CD; Added files: Index: src/sys/arch/i386/stand/efiboot/dev_net.c diff -u /dev/null src/sys/arch/i386/stand/efiboot/dev_net.c:1.1.2.2 --- /dev/null Wed Apr 11 14:51:43 2018 +++ src/sys/arch/i386/stand/efiboot/dev_net.c Wed Apr 11 14:51:43 2018 @@ -0,0 +1,3 @@ +/* $NetBSD: dev_net.c,v 1.1.2.2 2018/04/11 14:51:43 martin Exp $ */ + +#include <lib/libsa/dev_net.c> Index: src/sys/arch/i386/stand/efiboot/efinet.c diff -u /dev/null src/sys/arch/i386/stand/efiboot/efinet.c:1.1.2.2 --- /dev/null Wed Apr 11 14:51:43 2018 +++ src/sys/arch/i386/stand/efiboot/efinet.c Wed Apr 11 14:51:43 2018 @@ -0,0 +1,480 @@ +/* $NetBSD: efinet.c,v 1.1.2.2 2018/04/11 14:51:43 martin Exp $ */ + +/*- + * Copyright (c) 2001 Doug Rabson + * Copyright (c) 2002, 2006 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#if 0 +__FBSDID("$FreeBSD: head/stand/efi/libefi/efinet.c 321621 2017-07-27 15:06:34Z andrew $"); +#endif + +#include "efiboot.h" + +#include <lib/libsa/net.h> +#include <lib/libsa/netif.h> + +#include <bootinfo.h> +#include "devopen.h" + +#ifndef ETHER_ALIGN +#define ETHER_ALIGN 2 +#endif + +#define ETHER_EXT_LEN (ETHER_HDR_LEN + ETHER_CRC_LEN + ETHER_ALIGN) + +#if defined(DEBUG) || defined(ARP_DEBUG) || defined(BOOTP_DEBUG) || \ + defined(NET_DEBUG) || defined(NETIF_DEBUG) || defined(NFS_DEBUG) || \ + defined(RARP_DEBUG) || defined(RPC_DEBUG) +int debug = 1; +#else +int debug = 0; +#endif + +extern bool kernel_loaded; + +struct efinetinfo { + EFI_SIMPLE_NETWORK *net; + bool bootdev; + size_t pktbufsz; + UINT8 *pktbuf; + struct { + int type; + u_int tag; + } bus; +}; +static struct btinfo_netif bi_netif; + +static int efinet_match(struct netif *, void *); +static int efinet_probe(struct netif *, void *); +static void efinet_init(struct iodesc *, void *); +static int efinet_get(struct iodesc *, void *, size_t, saseconds_t); +static int efinet_put(struct iodesc *, void *, size_t); +static void efinet_end(struct netif *); + +struct netif_driver efinetif = { + .netif_bname = "net", + .netif_match = efinet_match, + .netif_probe = efinet_probe, + .netif_init = efinet_init, + .netif_get = efinet_get, + .netif_put = efinet_put, + .netif_end = efinet_end, + .netif_ifs = NULL, + .netif_nifs = 0 +}; + +#ifdef EFINET_DEBUG +static void +dump_mode(EFI_SIMPLE_NETWORK_MODE *mode) +{ + int i; + + printf("State = %x\n", mode->State); + printf("HwAddressSize = %u\n", mode->HwAddressSize); + printf("MediaHeaderSize = %u\n", mode->MediaHeaderSize); + printf("MaxPacketSize = %u\n", mode->MaxPacketSize); + printf("NvRamSize = %u\n", mode->NvRamSize); + printf("NvRamAccessSize = %u\n", mode->NvRamAccessSize); + printf("ReceiveFilterMask = %x\n", mode->ReceiveFilterMask); + printf("ReceiveFilterSetting = %u\n", mode->ReceiveFilterSetting); + printf("MaxMCastFilterCount = %u\n", mode->MaxMCastFilterCount); + printf("MCastFilterCount = %u\n", mode->MCastFilterCount); + printf("MCastFilter = {"); + for (i = 0; i < mode->MCastFilterCount; i++) + printf(" %s", ether_sprintf(mode->MCastFilter[i].Addr)); + printf(" }\n"); + printf("CurrentAddress = %s\n", + ether_sprintf(mode->CurrentAddress.Addr)); + printf("BroadcastAddress = %s\n", + ether_sprintf(mode->BroadcastAddress.Addr)); + printf("PermanentAddress = %s\n", + ether_sprintf(mode->PermanentAddress.Addr)); + printf("IfType = %u\n", mode->IfType); + printf("MacAddressChangeable = %d\n", mode->MacAddressChangeable); + printf("MultipleTxSupported = %d\n", mode->MultipleTxSupported); + printf("MediaPresentSupported = %d\n", mode->MediaPresentSupported); + printf("MediaPresent = %d\n", mode->MediaPresent); +} +#endif + +static int +efinet_match(struct netif *nif, void *machdep_hint) +{ + struct devdesc *dev = machdep_hint; + + if (dev->d_unit != nif->nif_unit) + return 0; + + return 1; +} + +static int +efinet_probe(struct netif *nif, void *machdep_hint) +{ + + return 0; +} + +static int +efinet_put(struct iodesc *desc, void *pkt, size_t len) +{ + struct netif *nif = desc->io_netif; + struct efinetinfo *eni = nif->nif_devdata; + EFI_SIMPLE_NETWORK *net; + EFI_STATUS status; + void *buf; + + if (eni == NULL) + return -1; + net = eni->net; + + status = uefi_call_wrapper(net->Transmit, 7, net, 0, (UINTN)len, pkt, NULL, + NULL, NULL); + if (EFI_ERROR(status)) + return -1; + + /* Wait for the buffer to be transmitted */ + do { + buf = NULL; /* XXX Is this needed? */ + status = uefi_call_wrapper(net->GetStatus, 3, net, NULL, &buf); + /* + * XXX EFI1.1 and the E1000 card returns a different + * address than we gave. Sigh. + */ + } while (!EFI_ERROR(status) && buf == NULL); + + /* XXX How do we deal with status != EFI_SUCCESS now? */ + return EFI_ERROR(status) ? -1 : len; +} + +static int +efinet_get(struct iodesc *desc, void *pkt, size_t len, saseconds_t timeout) +{ + struct netif *nif = desc->io_netif; + struct efinetinfo *eni = nif->nif_devdata; + EFI_SIMPLE_NETWORK *net; + EFI_STATUS status; + UINTN bufsz, rsz; + time_t t; + char *buf, *ptr; + int ret = -1; + + if (eni == NULL) + return -1; + net = eni->net; + + if (eni->pktbufsz < net->Mode->MaxPacketSize + ETHER_EXT_LEN) { + bufsz = net->Mode->MaxPacketSize + ETHER_EXT_LEN; + buf = alloc(bufsz); + if (buf == NULL) + return -1; + dealloc(eni->pktbuf, eni->pktbufsz); + eni->pktbufsz = bufsz; + eni->pktbuf = buf; + } + ptr = eni->pktbuf + ETHER_ALIGN; + + t = getsecs(); + while ((getsecs() - t) < timeout) { + rsz = eni->pktbufsz; + status = uefi_call_wrapper(net->Receive, 7, net, NULL, &rsz, ptr, + NULL, NULL, NULL); + if (!EFI_ERROR(status)) { + rsz = min(rsz, len); + memcpy(pkt, ptr, rsz); + ret = (int)rsz; + break; + } + if (status != EFI_NOT_READY) + break; + } + + return ret; +} + +static void +efinet_init(struct iodesc *desc, void *machdep_hint) +{ + struct netif *nif = desc->io_netif; + struct efinetinfo *eni; + EFI_SIMPLE_NETWORK *net; + EFI_STATUS status; + UINT32 mask; + + if (nif->nif_driver->netif_ifs[nif->nif_unit].dif_unit < 0) { + printf("Invalid network interface %d\n", nif->nif_unit); + return; + } + + eni = nif->nif_driver->netif_ifs[nif->nif_unit].dif_private; + nif->nif_devdata = eni; + net = eni->net; + if (net->Mode->State == EfiSimpleNetworkStopped) { + status = uefi_call_wrapper(net->Start, 1, net); + if (EFI_ERROR(status)) { + printf("net%d: cannot start interface (status=%" + PRIxMAX ")\n", nif->nif_unit, (uintmax_t)status); + return; + } + } + + if (net->Mode->State != EfiSimpleNetworkInitialized) { + status = uefi_call_wrapper(net->Initialize, 3, net, 0, 0); + if (EFI_ERROR(status)) { + printf("net%d: cannot init. interface (status=%" + PRIxMAX ")\n", nif->nif_unit, (uintmax_t)status); + return; + } + } + + mask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | + EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST; + + status = uefi_call_wrapper(net->ReceiveFilters, 6, net, mask, 0, FALSE, + 0, NULL); + if (EFI_ERROR(status)) { + printf("net%d: cannot set rx. filters (status=%" PRIxMAX ")\n", + nif->nif_unit, (uintmax_t)status); + return; + } + + if (!kernel_loaded) { + bi_netif.bus = eni->bus.type; + bi_netif.addr.tag = eni->bus.tag; + snprintf(bi_netif.ifname, sizeof(bi_netif.ifname), "net%d", + nif->nif_unit); + BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif)); + } + +#ifdef EFINET_DEBUG + dump_mode(net->Mode); +#endif + + memcpy(desc->myea, net->Mode->CurrentAddress.Addr, 6); + desc->xid = 1; +} + +static void +efinet_end(struct netif *nif) +{ + struct efinetinfo *eni = nif->nif_devdata; + EFI_SIMPLE_NETWORK *net; + + if (eni == NULL) + return; + net = eni->net; + + uefi_call_wrapper(net->Shutdown, 1, net); +} + +static bool +efi_net_pci_probe(struct efinetinfo *eni, EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *pdp) +{ + PCI_DEVICE_PATH *pci = (PCI_DEVICE_PATH *)dp; + int bus = -1; + + if (pdp != NULL && + DevicePathType(pdp) == ACPI_DEVICE_PATH && + (DevicePathSubType(pdp) == ACPI_DP || + DevicePathSubType(pdp) == EXPANDED_ACPI_DP)) { + ACPI_HID_DEVICE_PATH *acpi = (ACPI_HID_DEVICE_PATH *)pdp; + /* PCI root bus */ + if (acpi->HID == EISA_PNP_ID(0x0A08) || + acpi->HID == EISA_PNP_ID(0x0A03)) { + bus = acpi->UID; + } + } + if (bus < 0) + return false; + + eni->bus.type = BI_BUS_PCI; + eni->bus.tag = (bus & 0xff) << 8; + eni->bus.tag |= (pci->Device & 0x1f) << 3; + eni->bus.tag |= pci->Function & 0x7; + return true; +} + +void +efi_net_probe(void) +{ + struct efinetinfo *enis; + struct netif_dif *dif; + struct netif_stats *stats; + EFI_DEVICE_PATH *dp0, *dp, *pdp; + EFI_SIMPLE_NETWORK *net; + EFI_HANDLE *handles; + EFI_STATUS status; + UINTN i, nhandles; + int nifs; + bool found; + + status = LibLocateHandle(ByProtocol, &SimpleNetworkProtocol, NULL, + &nhandles, &handles); + if (EFI_ERROR(status) || nhandles == 0) + return; + + enis = alloc(nhandles * sizeof(*enis)); + if (enis == NULL) + return; + memset(enis, 0, nhandles * sizeof(*enis)); + + nifs = 0; + for (i = 0; i < nhandles; i++) { + status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i], + &DevicePathProtocol, (void **)&dp0); + if (EFI_ERROR(status)) + continue; + + found = false; + for (dp = dp0; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp)) { + if (DevicePathType(dp) == MESSAGING_DEVICE_PATH && + DevicePathSubType(dp) == MSG_MAC_ADDR_DP) { + found = true; + break; + } + } + if (!found) + continue; + + status = uefi_call_wrapper(BS->OpenProtocol, 6, handles[i], + &SimpleNetworkProtocol, (void **)&net, IH, NULL, + EFI_OPEN_PROTOCOL_EXCLUSIVE); + if (EFI_ERROR(status)) { + printf("Unable to open network interface %" PRIuMAX + " for exclusive access: %" PRIxMAX "\n", + (uintmax_t)i, (uintmax_t)status); + } + + found = false; + for (pdp = NULL, dp = dp0; + !IsDevicePathEnd(dp); + pdp = dp, dp = NextDevicePathNode(dp)) { + if (DevicePathType(dp) == HARDWARE_DEVICE_PATH) { + if (DevicePathSubType(dp) == HW_PCI_DP) + found = efi_net_pci_probe(&enis[nifs], + dp, pdp); + break; + } + } + if (found) { + enis[nifs].net = net; + enis[nifs].bootdev = efi_pxe_match_booted_interface( + &net->Mode->CurrentAddress, net->Mode->HwAddressSize); + enis[nifs].pktbufsz = net->Mode->MaxPacketSize + + ETHER_EXT_LEN; + enis[nifs].pktbuf = alloc(enis[nifs].pktbufsz); + if (enis[nifs].pktbuf == NULL) { + while (i-- > 0) { + dealloc(enis[i].pktbuf, enis[i].pktbufsz); + if (i == 0) + break; + } + dealloc(enis, nhandles * sizeof(*enis)); + FreePool(handles); + return; + } + nifs++; + } + } + + FreePool(handles); + + if (nifs == 0) + return; + + efinetif.netif_ifs = alloc(nifs * sizeof(*dif)); + stats = alloc(nifs * sizeof(*stats)); + if (efinetif.netif_ifs == NULL || stats == NULL) { + if (efinetif.netif_ifs != NULL) { + dealloc(efinetif.netif_ifs, nifs * sizeof(*dif)); + efinetif.netif_ifs = NULL; + } + if (stats != NULL) + dealloc(stats, nifs * sizeof(*stats)); + for (i = 0; i < nifs; i++) + dealloc(enis[i].pktbuf, enis[i].pktbufsz); + dealloc(enis, nhandles * sizeof(*enis)); + return; + } + memset(efinetif.netif_ifs, 0, nifs * sizeof(*dif)); + memset(stats, 0, nifs * sizeof(*stats)); + efinetif.netif_nifs = nifs; + + for (i = 0; i < nifs; i++) { + dif = &efinetif.netif_ifs[i]; + dif->dif_unit = i; + dif->dif_nsel = 1; + dif->dif_stats = &stats[i]; + dif->dif_private = &enis[i]; + } +} + +void +efi_net_show(void) +{ + const struct netif_dif *dif; + const struct efinetinfo *eni; + EFI_SIMPLE_NETWORK *net; + int i; + + for (i = 0; i < efinetif.netif_nifs; i++) { + dif = &efinetif.netif_ifs[i]; + eni = dif->dif_private; + net = eni->net; + + printf("net net%d", dif->dif_unit); + if (net->Mode != NULL) { + for (UINT32 x = 0; x < net->Mode->HwAddressSize; x++) { + printf("%c%02x", x == 0 ? ' ' : ':', + net->Mode->CurrentAddress.Addr[x]); + } + } + if (eni->bus.type == BI_BUS_PCI) { + printf(" pci%d,%d,%d", (eni->bus.tag >> 8) & 0xff, + (eni->bus.tag >> 3) & 0x1f, eni->bus.tag & 0x7); + } + if (eni->bootdev) + printf(" pxeboot"); + printf("\n"); + } +} + +int +efi_net_get_booted_interface_unit(void) +{ + const struct netif_dif *dif; + const struct efinetinfo *eni; + int i; + + for (i = 0; i < efinetif.netif_nifs; i++) { + dif = &efinetif.netif_ifs[i]; + eni = dif->dif_private; + if (eni->bootdev) + return dif->dif_unit; + } + return -1; +} Index: src/sys/arch/i386/stand/efiboot/efinet.h diff -u /dev/null src/sys/arch/i386/stand/efiboot/efinet.h:1.1.2.2 --- /dev/null Wed Apr 11 14:51:43 2018 +++ src/sys/arch/i386/stand/efiboot/efinet.h Wed Apr 11 14:51:43 2018 @@ -0,0 +1,29 @@ +/* $NetBSD: efinet.h,v 1.1.2.2 2018/04/11 14:51:43 martin Exp $ */ + +/*- + * Copyright (c) 2018 Kimihiro Nonaka <non...@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +extern struct netif_driver efinetif; Index: src/sys/arch/i386/stand/efiboot/efipxe.c diff -u /dev/null src/sys/arch/i386/stand/efiboot/efipxe.c:1.1.2.2 --- /dev/null Wed Apr 11 14:51:43 2018 +++ src/sys/arch/i386/stand/efiboot/efipxe.c Wed Apr 11 14:51:43 2018 @@ -0,0 +1,141 @@ +/* $NetBSD: efipxe.c,v 1.1.2.2 2018/04/11 14:51:43 martin Exp $ */ +/* $OpenBSD: efipxe.c,v 1.3 2018/01/30 20:19:06 naddy Exp $ */ + +/* + * Copyright (c) 2017 Patrick Wildt <patr...@blueri.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/queue.h> + +#include "efiboot.h" + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <lib/libsa/bootp.h> /* for VM_RFC1048 */ + + +struct efipxeinfo { + TAILQ_ENTRY(efipxeinfo) list; + + EFI_PXE_BASE_CODE *pxe; + EFI_SIMPLE_NETWORK *net; + EFI_MAC_ADDRESS mac; + UINT32 addrsz; +}; +TAILQ_HEAD(efipxeinfo_lh, efipxeinfo); +static struct efipxeinfo_lh efi_pxelist; +static int nefipxes; + +void +efi_pxe_probe(void) +{ + struct efipxeinfo *epi; + EFI_PXE_BASE_CODE *pxe; + EFI_DEVICE_PATH *dp; + EFI_SIMPLE_NETWORK *net; + EFI_HANDLE *handles; + EFI_STATUS status; + UINTN nhandles; + int i, depth; + bool found; + + TAILQ_INIT(&efi_pxelist); + + status = LibLocateHandle(ByProtocol, &PxeBaseCodeProtocol, NULL, + &nhandles, &handles); + if (EFI_ERROR(status)) + return; + + for (i = 0; i < nhandles; i++) { + status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i], + &DevicePathProtocol, (void **)&dp); + if (EFI_ERROR(status)) + continue; + + depth = efi_device_path_depth(efi_bootdp, MEDIA_DEVICE_PATH); + if (efi_device_path_ncmp(efi_bootdp, dp, depth)) + continue; + + status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i], + &PxeBaseCodeProtocol, (void **)&pxe); + if (EFI_ERROR(status)) + continue; + + if (pxe->Mode == NULL || + (!pxe->Mode->DhcpAckReceived && !pxe->Mode->PxeReplyReceived)) + continue; + + status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i], + &SimpleNetworkProtocol, (void **)&net); + if (EFI_ERROR(status)) + continue; + + if (net->Mode == NULL) + continue; + + found = false; + TAILQ_FOREACH(epi, &efi_pxelist, list) { + if (net->Mode->HwAddressSize == epi->addrsz && + memcmp(net->Mode->CurrentAddress.Addr, epi->mac.Addr, + net->Mode->HwAddressSize) == 0) { + found = true; + break; + } + } + if (found) + continue; + + epi = alloc(sizeof(*epi)); + if (epi == NULL) + continue; + + memset(epi, 0, sizeof(*epi)); + epi->pxe = pxe; + epi->net = net; + epi->addrsz = net->Mode->HwAddressSize; + memcpy(epi->mac.Addr, net->Mode->CurrentAddress.Addr, epi->addrsz); + + TAILQ_INSERT_TAIL(&efi_pxelist, epi, list); + nefipxes++; + } +} + +void +efi_pxe_show(void) +{ + const struct efipxeinfo *epi; + UINT32 i, n; + + n = 0; + TAILQ_FOREACH(epi, &efi_pxelist, list) { + printf("pxe pxe%d", n++); + for (i = 0; i < epi->addrsz; i++) + printf("%c%02x", i == 0 ? ' ' : ':', epi->mac.Addr[i]); + printf("\n"); + } +} + +bool +efi_pxe_match_booted_interface(const EFI_MAC_ADDRESS *mac, UINT32 addrsz) +{ + const struct efipxeinfo *epi; + + TAILQ_FOREACH(epi, &efi_pxelist, list) { + if (addrsz == epi->addrsz && + memcmp(mac->Addr, epi->mac.Addr, addrsz) == 0) + return true; + } + return false; +}