Module Name: src
Committed By: jmcneill
Date: Mon Sep 3 00:04:02 UTC 2018
Modified Files:
src/sys/stand/efiboot: Makefile.efiboot boot.c conf.c devopen.c
efiboot.c efiboot.h version
Added Files:
src/sys/stand/efiboot: dev_net.c efigetsecs.c efinet.c efinet.h
efipxe.c
Log Message:
Add PXE support.
To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/stand/efiboot/Makefile.efiboot \
src/sys/stand/efiboot/conf.c src/sys/stand/efiboot/devopen.c \
src/sys/stand/efiboot/efiboot.h
cvs rdiff -u -r1.3 -r1.4 src/sys/stand/efiboot/boot.c
cvs rdiff -u -r0 -r1.1 src/sys/stand/efiboot/dev_net.c \
src/sys/stand/efiboot/efinet.c src/sys/stand/efiboot/efinet.h \
src/sys/stand/efiboot/efipxe.c
cvs rdiff -u -r1.4 -r1.5 src/sys/stand/efiboot/efiboot.c
cvs rdiff -u -r0 -r1.3 src/sys/stand/efiboot/efigetsecs.c
cvs rdiff -u -r1.1 -r1.2 src/sys/stand/efiboot/version
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/stand/efiboot/Makefile.efiboot
diff -u src/sys/stand/efiboot/Makefile.efiboot:1.2 src/sys/stand/efiboot/Makefile.efiboot:1.3
--- src/sys/stand/efiboot/Makefile.efiboot:1.2 Sun Aug 26 21:28:18 2018
+++ src/sys/stand/efiboot/Makefile.efiboot Mon Sep 3 00:04:02 2018
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.efiboot,v 1.2 2018/08/26 21:28:18 jmcneill Exp $
+# $NetBSD: Makefile.efiboot,v 1.3 2018/09/03 00:04:02 jmcneill Exp $
S= ${.CURDIR}/../../..
@@ -21,8 +21,8 @@ AFLAGS.start.S= ${${ACTIVE_CC} == "clang
.PATH: ${EFIDIR}/gnuefi
SOURCES= crt0-efi-${GNUEFIARCH}.S reloc_${GNUEFIARCH}.c
-SOURCES+= boot.c conf.c console.c devopen.c exec.c panic.c prompt.c
-SOURCES+= efiboot.c efichar.c efidev.c efifdt.c efifile.c efiblock.c
+SOURCES+= boot.c conf.c console.c dev_net.c devopen.c exec.c panic.c prompt.c
+SOURCES+= efiboot.c efichar.c efidev.c efigetsecs.c efifdt.c efifile.c efiblock.c efinet.c efipxe.c
.PATH: ${S}/external/bsd/libfdt/dist
CPPFLAGS+= -I${S}/external/bsd/libfdt/dist
@@ -68,12 +68,12 @@ CPPFLAGS+= -Wno-pointer-sign
CPPFLAGS+= -DHEAP_VARIABLE
#CPPFLAGS+= -DSUPPORT_CD9660
CPPFLAGS+= -D"devb2cdb(bno)=(bno)"
-#CPPFLAGS+= -DSUPPORT_DOSFS
+CPPFLAGS+= -DSUPPORT_DOSFS
#CPPFLAGS+= -DSUPPORT_EXT2FS
-#CPPFLAGS+= -DSUPPORT_BOOTP
-#CPPFLAGS+= -DSUPPORT_DHCP
+CPPFLAGS+= -DSUPPORT_BOOTP
+CPPFLAGS+= -DSUPPORT_DHCP
#CPPFLAGS+= -DSUPPORT_NFS
-#CPPFLAGS+= -DSUPPORT_TFTP
+CPPFLAGS+= -DSUPPORT_TFTP
CPPFLAGS+= -DLIBSA_ENABLE_LS_OP
#CPPFLAGS+= -DARP_DEBUG
@@ -92,7 +92,7 @@ SAMISCCPPFLAGS+= -D"cdb2devb(bno)=(bno)"
SA_AS= library
SAMISCMAKEFLAGS+="SA_USE_LOADFILE=yes"
SAMISCMAKEFLAGS+="SA_USE_CREAD=yes"
-#SAMISCMAKEFLAGS+="SA_INCLUDE_NET=yes"
+SAMISCMAKEFLAGS+="SA_INCLUDE_NET=yes"
SAMISCMAKEFLAGS+="SA_ENABLE_LS_OP=yes"
.include "${S}/lib/libsa/Makefile.inc"
LIBSA= ${SALIB}
Index: src/sys/stand/efiboot/conf.c
diff -u src/sys/stand/efiboot/conf.c:1.2 src/sys/stand/efiboot/conf.c:1.3
--- src/sys/stand/efiboot/conf.c:1.2 Sun Aug 26 21:28:18 2018
+++ src/sys/stand/efiboot/conf.c Mon Sep 3 00:04:02 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: conf.c,v 1.2 2018/08/26 21:28:18 jmcneill Exp $ */
+/* $NetBSD: conf.c,v 1.3 2018/09/03 00:04:02 jmcneill Exp $ */
/*-
* Copyright (c) 2018 Jared McNeill <[email protected]>
@@ -33,20 +33,29 @@
#include <lib/libsa/stand.h>
#include <lib/libsa/ufs.h>
#include <lib/libsa/dosfs.h>
+#include <lib/libsa/tftp.h>
+#include <lib/libsa/net.h>
+#include <lib/libsa/dev_net.h>
struct devsw devsw[] = {
{ "efifile", efi_file_strategy, efi_file_open, efi_file_close, noioctl },
{ "efiblock", efi_block_strategy, efi_block_open, efi_block_close, noioctl },
+ { "net", net_strategy, net_open, net_close, noioctl },
};
int ndevs = __arraycount(devsw);
struct netif_driver *netif_drivers[] = {
+ &efinetif,
};
int n_netif_drivers = __arraycount(netif_drivers);
struct fs_ops file_system[] = {
+ FS_OPS(null),
FS_OPS(ffsv1),
FS_OPS(ffsv2),
FS_OPS(dosfs),
};
int nfsys = __arraycount(file_system);
+
+struct fs_ops null_fs_ops = FS_OPS(null);
+struct fs_ops tftp_fs_ops = FS_OPS(tftp);
Index: src/sys/stand/efiboot/devopen.c
diff -u src/sys/stand/efiboot/devopen.c:1.2 src/sys/stand/efiboot/devopen.c:1.3
--- src/sys/stand/efiboot/devopen.c:1.2 Sun Aug 26 21:28:18 2018
+++ src/sys/stand/efiboot/devopen.c Mon Sep 3 00:04:02 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: devopen.c,v 1.2 2018/08/26 21:28:18 jmcneill Exp $ */
+/* $NetBSD: devopen.c,v 1.3 2018/09/03 00:04:02 jmcneill Exp $ */
/*-
* Copyright (c) 2018 Jared McNeill <[email protected]>
@@ -35,7 +35,11 @@ devopen(struct open_file *f, const char
{
int error;
- error = efi_block_open(f, fname, file);
+ error = efi_net_open(f, fname, file);
+ file_system[0] = error ? null_fs_ops : tftp_fs_ops;
+
+ if (error)
+ error = efi_block_open(f, fname, file);
if (error)
error = efi_file_open(f, fname);
Index: src/sys/stand/efiboot/efiboot.h
diff -u src/sys/stand/efiboot/efiboot.h:1.2 src/sys/stand/efiboot/efiboot.h:1.3
--- src/sys/stand/efiboot/efiboot.h:1.2 Sun Aug 26 21:28:18 2018
+++ src/sys/stand/efiboot/efiboot.h Mon Sep 3 00:04:02 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: efiboot.h,v 1.2 2018/08/26 21:28:18 jmcneill Exp $ */
+/* $NetBSD: efiboot.h,v 1.3 2018/09/03 00:04:02 jmcneill Exp $ */
/*-
* Copyright (c) 2016 Kimihiro Nonaka <[email protected]>
@@ -40,6 +40,10 @@ struct boot_command {
const char *c_help;
};
+/* conf.c */
+extern struct fs_ops null_fs_ops;
+extern struct fs_ops tftp_fs_ops;
+
/* boot.c */
void boot(void);
void clearit(void);
@@ -69,6 +73,18 @@ int utf8_to_ucs2(const char *, CHAR16 **
int efi_device_path_depth(EFI_DEVICE_PATH *dp, int);
int efi_device_path_ncmp(EFI_DEVICE_PATH *, EFI_DEVICE_PATH *, int);
+/* efinet.c */
+int efi_net_open(struct open_file *, ...);
+void efi_net_probe(void);
+void efi_net_show(void);
+int efi_net_get_booted_interface_unit(void);
+extern struct netif_driver efinetif;
+
+/* efipxe.c */
+void efi_pxe_probe(void);
+void efi_pxe_show(void);
+bool efi_pxe_match_booted_interface(const EFI_MAC_ADDRESS *, UINT32);
+
/* exec.c */
int exec_netbsd(const char *, const char *);
Index: src/sys/stand/efiboot/boot.c
diff -u src/sys/stand/efiboot/boot.c:1.3 src/sys/stand/efiboot/boot.c:1.4
--- src/sys/stand/efiboot/boot.c:1.3 Sun Aug 26 21:28:18 2018
+++ src/sys/stand/efiboot/boot.c Mon Sep 3 00:04:02 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: boot.c,v 1.3 2018/08/26 21:28:18 jmcneill Exp $ */
+/* $NetBSD: boot.c,v 1.4 2018/09/03 00:04:02 jmcneill Exp $ */
/*-
* Copyright (c) 2016 Kimihiro Nonaka <[email protected]>
@@ -63,7 +63,7 @@ void command_quit(char *);
const struct boot_command commands[] = {
{ "boot", command_boot, "boot [fsN:][filename] [args]\n (ex. \"fs0:\\netbsd.old -s\"" },
{ "dev", command_dev, "dev" },
- { "ls", command_ls, "ls [hdNn:/path]\n" },
+ { "ls", command_ls, "ls [hdNn:/path]" },
{ "version", command_version, "version" },
{ "help", command_help, "help|?" },
{ "?", command_help, NULL },
@@ -99,6 +99,8 @@ command_dev(char *arg)
set_default_device(arg);
} else {
efi_block_show();
+ efi_net_show();
+ efi_pxe_show();
}
if (strlen(default_device) > 0) {
Index: src/sys/stand/efiboot/efiboot.c
diff -u src/sys/stand/efiboot/efiboot.c:1.4 src/sys/stand/efiboot/efiboot.c:1.5
--- src/sys/stand/efiboot/efiboot.c:1.4 Sun Aug 26 21:28:18 2018
+++ src/sys/stand/efiboot/efiboot.c Mon Sep 3 00:04:02 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: efiboot.c,v 1.4 2018/08/26 21:28:18 jmcneill Exp $ */
+/* $NetBSD: efiboot.c,v 1.5 2018/09/03 00:04:02 jmcneill Exp $ */
/*-
* Copyright (c) 2018 Jared McNeill <[email protected]>
@@ -31,7 +31,7 @@
#include "efiblock.h"
#include "efifdt.h"
-EFI_HANDLE efi_ih;
+EFI_HANDLE IH;
EFI_DEVICE_PATH *efi_bootdp;
EFI_LOADED_IMAGE *efi_li;
@@ -47,7 +47,7 @@ efi_main(EFI_HANDLE imageHandle, EFI_SYS
EFI_STATUS status;
u_int sz = EFI_SIZE_TO_PAGES(heap_size);
- efi_ih = imageHandle;
+ IH = imageHandle;
InitializeLib(imageHandle, systemTable);
@@ -76,6 +76,8 @@ efi_main(EFI_HANDLE imageHandle, EFI_SYS
efi_fdt_probe();
efi_file_system_probe();
efi_block_probe();
+ efi_pxe_probe();
+ efi_net_probe();
boot();
@@ -91,7 +93,7 @@ efi_cleanup(void)
LibMemoryMap(&nentries, &mapkey, &descsize, &descver);
- status = uefi_call_wrapper(BS->ExitBootServices, 2, efi_ih, mapkey);
+ status = uefi_call_wrapper(BS->ExitBootServices, 2, IH, mapkey);
if (EFI_ERROR(status))
printf("WARNING: ExitBootServices failed\n");
}
@@ -101,7 +103,7 @@ efi_exit(void)
{
EFI_STATUS status;
- status = uefi_call_wrapper(BS->Exit, 4, efi_ih, EFI_ABORTED, 0, NULL);
+ status = uefi_call_wrapper(BS->Exit, 4, IH, EFI_ABORTED, 0, NULL);
if (EFI_ERROR(status))
printf("WARNING: Exit failed\n");
}
Index: src/sys/stand/efiboot/version
diff -u src/sys/stand/efiboot/version:1.1 src/sys/stand/efiboot/version:1.2
--- src/sys/stand/efiboot/version:1.1 Fri Aug 24 02:01:06 2018
+++ src/sys/stand/efiboot/version Mon Sep 3 00:04:02 2018
@@ -1,7 +1,8 @@
-$NetBSD: version,v 1.1 2018/08/24 02:01:06 jmcneill Exp $
+$NetBSD: version,v 1.2 2018/09/03 00:04:02 jmcneill Exp $
NOTE ANY CHANGES YOU MAKE TO THE EFI BOOTLOADER HERE. The format of this
file is important - make sure the entries are appended on end, last item
is taken as the current.
1.0: Initial version.
+1.1: Add PXE booting support.
Added files:
Index: src/sys/stand/efiboot/dev_net.c
diff -u /dev/null src/sys/stand/efiboot/dev_net.c:1.1
--- /dev/null Mon Sep 3 00:04:02 2018
+++ src/sys/stand/efiboot/dev_net.c Mon Sep 3 00:04:02 2018
@@ -0,0 +1,96 @@
+/* $NetBSD: dev_net.c,v 1.1 2018/09/03 00:04:02 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2018 Jared McNeill <[email protected]>
+ * 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.
+ */
+
+#include "efiboot.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+
+#include <lib/libsa/net.h>
+#include <lib/libsa/netif.h>
+#include <lib/libsa/bootparam.h>
+#include <lib/libsa/bootp.h>
+
+#include "dev_net.h"
+
+static int net_socket = -1;
+
+int
+net_open(struct open_file *f, ...)
+{
+ va_list ap;
+ char *devname;
+ int error;
+
+ va_start(ap, f);
+ devname = va_arg(ap, char *);
+ va_end(ap);
+
+ if (net_socket < 0)
+ net_socket = netif_open(devname);
+ if (net_socket < 0)
+ return ENXIO;
+
+ if (myip.s_addr == INADDR_ANY) {
+ bootp(net_socket);
+
+ if (myip.s_addr == INADDR_ANY) {
+ error = EIO;
+ goto fail;
+ }
+
+ printf("boot: client ip: %s\n", inet_ntoa(myip));
+ printf("boot: server ip: %s\n", inet_ntoa(rootip));
+ }
+
+ f->f_devdata = &net_socket;
+
+ return 0;
+
+fail:
+ printf("net_open failed: %d\n", error);
+ netif_close(net_socket);
+ net_socket = -1;
+ return error;
+}
+
+int
+net_close(struct open_file *f)
+{
+ f->f_devdata = NULL;
+
+ return 0;
+}
+
+int
+net_strategy(void *devdata, int rw, daddr_t dblk, size_t size, void *buf, size_t *rsize)
+{
+ return EIO;
+}
Index: src/sys/stand/efiboot/efinet.c
diff -u /dev/null src/sys/stand/efiboot/efinet.c:1.1
--- /dev/null Mon Sep 3 00:04:02 2018
+++ src/sys/stand/efiboot/efinet.c Mon Sep 3 00:04:02 2018
@@ -0,0 +1,529 @@
+/* $NetBSD: efinet.c,v 1.1 2018/09/03 00:04:02 jmcneill 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>
+
+#include "efiboot.h"
+
+#include <lib/libsa/net.h>
+#include <lib/libsa/netif.h>
+#include <lib/libsa/dev_net.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;
+};
+#if notyet
+static struct btinfo_netif bi_netif;
+#endif
+
+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) && status != EFI_INVALID_PARAMETER) {
+ printf("net%d: cannot set rx. filters (status=%" PRIxMAX ")\n",
+ nif->nif_unit, (uintmax_t)status);
+ return;
+ }
+
+#if notyet
+ 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));
+ }
+#endif
+
+#ifdef EFINET_DEBUG
+ dump_mode(net->Mode);
+#endif
+
+ memcpy(desc->myea, net->Mode->PermanentAddress.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)
+{
+#if notyet
+ PCI_DEVICE_PATH *pci = (PCI_DEVICE_PATH *)dp;
+#endif
+ 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;
+
+#if notyet
+ 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;
+#endif
+ 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->PermanentAddress, 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->PermanentAddress.Addr[x]);
+ }
+ }
+#if notyet
+ 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);
+ }
+#endif
+ 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;
+}
+
+int
+efi_net_open(struct open_file *f, ...)
+{
+ struct devdesc desc;
+ const char *fname;
+ char **file, *ep;
+ intmax_t dev;
+ va_list ap;
+ int n;
+
+ va_start(ap, f);
+ fname = va_arg(ap, const char *);
+ file = va_arg(ap, char **);
+ va_end(ap);
+
+ if (strncmp(fname, "net", 3) != 0)
+ return EINVAL;
+ dev = strtoimax(fname + 3, &ep, 10);
+ if (dev < 0 || dev >= efinetif.netif_nifs)
+ return ENXIO;
+ if (*ep != ':')
+ return ENXIO;
+
+ for (n = 0; n < ndevs; n++)
+ if (strcmp(DEV_NAME(&devsw[n]), "net") == 0) {
+ f->f_dev = &devsw[n];
+ break;
+ }
+ if (n == ndevs)
+ return ENXIO;
+
+ *file = ep + 1;
+
+ //try_bootp = 1;
+
+ memset(&desc, 0, sizeof(desc));
+ strlcpy(desc.d_name, "net", sizeof(desc.d_name));
+ desc.d_unit = dev;
+
+ return DEV_OPEN(f->f_dev)(f, &desc);
+}
Index: src/sys/stand/efiboot/efinet.h
diff -u /dev/null src/sys/stand/efiboot/efinet.h:1.1
--- /dev/null Mon Sep 3 00:04:02 2018
+++ src/sys/stand/efiboot/efinet.h Mon Sep 3 00:04:02 2018
@@ -0,0 +1,29 @@
+/* $NetBSD: efinet.h,v 1.1 2018/09/03 00:04:02 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2018 Kimihiro Nonaka <[email protected]>
+ * 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/stand/efiboot/efipxe.c
diff -u /dev/null src/sys/stand/efiboot/efipxe.c:1.1
--- /dev/null Mon Sep 3 00:04:02 2018
+++ src/sys/stand/efiboot/efipxe.c Mon Sep 3 00:04:02 2018
@@ -0,0 +1,141 @@
+/* $NetBSD: efipxe.c,v 1.1 2018/09/03 00:04:02 jmcneill Exp $ */
+/* $OpenBSD: efipxe.c,v 1.3 2018/01/30 20:19:06 naddy Exp $ */
+
+/*
+ * Copyright (c) 2017 Patrick Wildt <[email protected]>
+ *
+ * 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;
+}
Index: src/sys/stand/efiboot/efigetsecs.c
diff -u /dev/null src/sys/stand/efiboot/efigetsecs.c:1.3
--- /dev/null Mon Sep 3 00:04:02 2018
+++ src/sys/stand/efiboot/efigetsecs.c Mon Sep 3 00:04:02 2018
@@ -0,0 +1,81 @@
+/* $NetBSD: efigetsecs.c,v 1.3 2018/09/03 00:04:02 jmcneill Exp $ */
+
+/*
+ * Copyright (c) 2015 YASUOKA Masahiko <[email protected]>
+ * Copyright (c) 2018 Jared McNeill <[email protected]>
+ *
+ * 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 "efiboot.h"
+
+#include <lib/libsa/net.h>
+
+static EFI_EVENT getsecs_ev = 0;
+static satime_t getsecs_val = 0;
+
+static satime_t
+getsecs_rtc(void)
+{
+ static const int daytab[][14] = {
+ { 0, -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 },
+ { 0, -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+ };
+ EFI_TIME t;
+ satime_t r;
+ int y;
+#define isleap(_y) (((_y) % 4) == 0 && (((_y) % 100) != 0 || ((_y) % 400) == 0))
+
+ uefi_call_wrapper(RT->GetTime, 2, &t, NULL);
+
+ /* Calc days from UNIX epoch */
+ r = (t.Year - 1970) * 365;
+ for (y = 1970; y < t.Year; y++) {
+ if (isleap(y))
+ r++;
+ }
+ r += daytab[isleap(t.Year) ? 1 : 0][t.Month] + t.Day;
+
+ /* Calc secs */
+ r *= 60 * 60 * 24;
+ r += ((t.Hour * 60) + t.Minute) * 60 + t.Second;
+ if (-24 * 60 < t.TimeZone && t.TimeZone < 24 * 60)
+ r += t.TimeZone * 60;
+
+ return r;
+}
+
+static void
+getsecs_notify_func(EFI_EVENT ev, VOID *context)
+{
+ getsecs_val++;
+}
+
+satime_t
+getsecs(void)
+{
+ EFI_STATUS status;
+
+ if (getsecs_ev == 0) {
+ status = uefi_call_wrapper(BS->CreateEvent, 5, EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
+ getsecs_notify_func, 0, &getsecs_ev);
+ if (EFI_ERROR(status))
+ panic("%s: couldn't create event timer: 0x%lx", __func__, status);
+ status = uefi_call_wrapper(BS->SetTimer, 3, getsecs_ev, TimerPeriodic, 10000000); /* 1s in "100ns" units */
+ if (EFI_ERROR(status))
+ panic("%s: couldn't start event timer: 0x%lx", __func__, status);
+ getsecs_val = getsecs_rtc();
+ }
+
+ return getsecs_val;
+}