summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2023-10-06 18:37:21 +0200
committerSimon Rettberg2023-10-06 18:37:21 +0200
commit95a57769874a70456670984debc05084feb75f6b (patch)
tree9943c86b682e1b1d21a0439637b3849840a50137
parent[efi] Remove old RDRAND hack; now officially supported (diff)
parent[libc] Use wall clock time as seed for the (non-cryptographic) RNG (diff)
downloadipxe-95a57769874a70456670984debc05084feb75f6b.tar.gz
ipxe-95a57769874a70456670984debc05084feb75f6b.tar.xz
ipxe-95a57769874a70456670984debc05084feb75f6b.zip
Merge branch 'master' into openslx
-rw-r--r--.github/workflows/build.yml3
-rw-r--r--src/Makefile.efi6
-rw-r--r--src/Makefile.housekeeping10
-rw-r--r--src/arch/arm/Makefile1
-rw-r--r--src/arch/arm/core/arm_io.c7
-rw-r--r--src/arch/arm/include/bits/pci_io.h2
-rw-r--r--src/arch/arm/include/ipxe/arm_io.h54
-rw-r--r--src/arch/arm64/core/setjmp.S1
-rw-r--r--src/arch/i386/core/gdbidt.S1
-rw-r--r--src/arch/i386/core/setjmp.S1
-rw-r--r--src/arch/i386/tests/gdbstub_test.S1
-rw-r--r--src/arch/loong64/Makefile1
-rw-r--r--src/arch/loong64/Makefile.efi14
-rw-r--r--src/arch/loong64/core/loong64_io.c46
-rw-r--r--src/arch/loong64/include/bits/io.h2
-rw-r--r--src/arch/loong64/include/bits/nap.h4
-rw-r--r--src/arch/loong64/include/ipxe/efi/efiloong64_nap.h18
-rw-r--r--src/arch/loong64/include/ipxe/loong64_io.h82
-rw-r--r--src/arch/loong64/interface/efi/efiloong64_nap.c53
-rw-r--r--src/arch/x86/Makefile.pcbios17
-rw-r--r--src/arch/x86/core/patch_cf.S1
-rw-r--r--src/arch/x86/core/stack.S1
-rw-r--r--src/arch/x86/core/stack16.S1
-rw-r--r--src/arch/x86/drivers/net/undiisr.S1
-rw-r--r--src/arch/x86/image/bzimage.c4
-rw-r--r--src/arch/x86/image/multiboot.c4
-rw-r--r--src/arch/x86/include/librm.h6
-rw-r--r--src/arch/x86/interface/pcbios/bios_console.c59
-rw-r--r--src/arch/x86/interface/pcbios/e820mangler.S1
-rw-r--r--src/arch/x86/interface/pxe/pxe_call.c3
-rw-r--r--src/arch/x86/interface/pxe/pxe_entry.S1
-rw-r--r--src/arch/x86/interface/syslinux/com32_wrapper.S1
-rw-r--r--src/arch/x86/interface/vmware/guestinfo.c46
-rw-r--r--src/arch/x86/prefix/bootpart.S1
-rw-r--r--src/arch/x86/prefix/dskprefix.S1
-rw-r--r--src/arch/x86/prefix/exeprefix.S1
-rw-r--r--src/arch/x86/prefix/hdprefix.S1
-rw-r--r--src/arch/x86/prefix/libprefix.S1
-rw-r--r--src/arch/x86/prefix/lkrnprefix.S1
-rw-r--r--src/arch/x86/prefix/mbr.S1
-rw-r--r--src/arch/x86/prefix/mromprefix.S1
-rw-r--r--src/arch/x86/prefix/nbiprefix.S1
-rw-r--r--src/arch/x86/prefix/nullprefix.S1
-rw-r--r--src/arch/x86/prefix/pxeprefix.S1
-rw-r--r--src/arch/x86/prefix/rawprefix.S1
-rw-r--r--src/arch/x86/prefix/romprefix.S1
-rw-r--r--src/arch/x86/prefix/undiloader.S1
-rw-r--r--src/arch/x86/prefix/unlzma.S1
-rw-r--r--src/arch/x86/prefix/usbdisk.S1
-rw-r--r--src/arch/x86/transitions/liba20.S1
-rw-r--r--src/arch/x86/transitions/libkir.S1
-rw-r--r--src/arch/x86/transitions/librm.S2
-rw-r--r--src/arch/x86_64/core/gdbidt.S1
-rw-r--r--src/arch/x86_64/core/setjmp.S1
-rw-r--r--src/config/config.c6
-rw-r--r--src/config/defaults/efi.h7
-rw-r--r--src/config/general.h1
-rw-r--r--src/config/settings.h2
-rw-r--r--src/core/cachedhcp.c3
-rw-r--r--src/core/image.c69
-rw-r--r--src/core/interface.c1
-rw-r--r--src/core/parseopt.c15
-rw-r--r--src/core/random.c8
-rw-r--r--src/core/xfer.c3
-rw-r--r--src/crypto/asn1.c26
-rw-r--r--src/crypto/rsa.c19
-rw-r--r--src/drivers/bus/virtio-pci.c4
-rw-r--r--src/drivers/linux/af_packet.c2
-rw-r--r--src/drivers/linux/tap.c7
-rw-r--r--src/drivers/net/3c90x.c20
-rw-r--r--src/drivers/net/atl1e.c18
-rw-r--r--src/drivers/net/b44.c16
-rw-r--r--src/drivers/net/bnxt/bnxt.c18
-rw-r--r--src/drivers/net/eepro100.c2
-rw-r--r--src/drivers/net/efi/nii.c10
-rw-r--r--src/drivers/net/efi/snpnet.c6
-rw-r--r--src/drivers/net/etherfabric.c14
-rw-r--r--src/drivers/net/forcedeth.c18
-rw-r--r--src/drivers/net/igbvf/igbvf_main.c18
-rw-r--r--src/drivers/net/jme.c2
-rw-r--r--src/drivers/net/netfront.c4
-rw-r--r--src/drivers/net/pcnet32.c16
-rw-r--r--src/drivers/net/phantom/phantom.c18
-rw-r--r--src/drivers/net/sfc/efx_common.c4
-rw-r--r--src/drivers/net/sfc/efx_hunt.c16
-rw-r--r--src/drivers/net/sfc/sfc_hunt.c10
-rw-r--r--src/drivers/net/sis190.c38
-rwxr-xr-xsrc/drivers/net/skge.c42
-rw-r--r--src/drivers/net/sky2.c30
-rw-r--r--src/drivers/net/tg3/tg3.c16
-rw-r--r--src/drivers/net/tg3/tg3_hw.c2
-rw-r--r--src/drivers/net/vmxnet3.c26
-rw-r--r--src/drivers/net/vxge/vxge_main.c14
-rw-r--r--src/drivers/usb/usbkbd.c4
-rw-r--r--src/hci/commands/image_cmd.c2
-rw-r--r--src/hci/commands/shim_cmd.c131
-rw-r--r--src/image/efi_image.c133
-rw-r--r--src/image/script.c7
-rw-r--r--src/include/ctype.h11
-rw-r--r--src/include/ipxe/asn1.h2
-rw-r--r--src/include/ipxe/dhcp.h3
-rw-r--r--src/include/ipxe/dummy_pio.h64
-rw-r--r--src/include/ipxe/eap.h21
-rw-r--r--src/include/ipxe/eapol.h21
-rw-r--r--src/include/ipxe/efi/AArch64/ProcessorBind.h34
-rw-r--r--src/include/ipxe/efi/Base.h110
-rw-r--r--src/include/ipxe/efi/Ia32/ProcessorBind.h8
-rw-r--r--src/include/ipxe/efi/IndustryStandard/PeImage.h44
-rw-r--r--src/include/ipxe/efi/Library/BaseLib.h50
-rw-r--r--src/include/ipxe/efi/Protocol/DebugSupport.h34
-rw-r--r--src/include/ipxe/efi/Protocol/Dhcp6.h782
-rw-r--r--src/include/ipxe/efi/Protocol/Dns4.h538
-rw-r--r--src/include/ipxe/efi/Protocol/Dns6.h535
-rw-r--r--src/include/ipxe/efi/Protocol/Http.h516
-rw-r--r--src/include/ipxe/efi/Protocol/Ip4Config2.h318
-rw-r--r--src/include/ipxe/efi/Protocol/Ip6.h948
-rw-r--r--src/include/ipxe/efi/Protocol/Ip6Config.h369
-rw-r--r--src/include/ipxe/efi/Protocol/Mtftp6.h820
-rw-r--r--src/include/ipxe/efi/Protocol/ShimLock.h31
-rw-r--r--src/include/ipxe/efi/Protocol/Tcp6.h858
-rw-r--r--src/include/ipxe/efi/Protocol/Udp6.h576
-rw-r--r--src/include/ipxe/efi/Uefi/UefiSpec.h4
-rw-r--r--src/include/ipxe/efi/X64/ProcessorBind.h22
-rw-r--r--src/include/ipxe/efi/efi.h41
-rw-r--r--src/include/ipxe/efi/efi_image.h27
-rw-r--r--src/include/ipxe/efi/efi_shim.h24
-rw-r--r--src/include/ipxe/efi/efi_strings.h2
-rw-r--r--src/include/ipxe/errfile.h3
-rw-r--r--src/include/ipxe/image.h66
-rw-r--r--src/include/ipxe/interface.h72
-rw-r--r--src/include/ipxe/keymap.h8
-rw-r--r--src/include/ipxe/keys.h49
-rw-r--r--src/include/ipxe/netdevice.h24
-rw-r--r--src/include/usr/shimmgmt.h17
-rw-r--r--src/interface/efi/efi_debug.c98
-rw-r--r--src/interface/efi/efi_file.c116
-rw-r--r--src/interface/efi/efi_guid.c87
-rw-r--r--src/interface/efi/efi_settings.c236
-rw-r--r--src/interface/efi/efi_shim.c402
-rw-r--r--src/interface/efi/efi_snp.c9
-rw-r--r--src/interface/efi/efi_strings.c44
-rw-r--r--src/interface/efi/efi_veto.c160
-rw-r--r--src/net/80211/wpa.c11
-rw-r--r--src/net/eap.c43
-rw-r--r--src/net/eapol.c196
-rw-r--r--src/net/fcoe.c88
-rw-r--r--src/net/infiniband/xsigo.c4
-rw-r--r--src/net/ipv6.c39
-rw-r--r--src/net/lldp.c95
-rw-r--r--src/net/neighbour.c3
-rw-r--r--src/net/netdevice.c77
-rw-r--r--src/net/udp/dhcp.c7
-rw-r--r--src/net/udp/ntp.c10
-rw-r--r--src/net/vlan.c9
-rw-r--r--src/tests/rsa_test.c60
-rw-r--r--src/usr/imgmgmt.c10
-rw-r--r--src/usr/shimmgmt.c61
-rw-r--r--src/util/elf2efi.c74
158 files changed, 9502 insertions, 792 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 72a1234b..232375ad 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -49,7 +49,8 @@ jobs:
sudo apt update
sudo apt install -y -o Acquire::Retries=50 \
mtools syslinux isolinux \
- libc6-dev-i386 libc6-dbg:i386 valgrind
+ libc6-dev-i386 valgrind \
+ libgcc-s1:i386 libc6-dbg:i386
- name: Build (BIOS)
run: |
make -j 4 -C src
diff --git a/src/Makefile.efi b/src/Makefile.efi
index bd479b3d..6e8ad46b 100644
--- a/src/Makefile.efi
+++ b/src/Makefile.efi
@@ -50,6 +50,10 @@ $(BIN)/efidrv.cab : $(BIN)/alldrv.efis # $(ALL_drv.efi) is not yet defined
$(QM)$(ECHO) " [CAB] $@"
$(Q)$(LCAB) -n -q $(ALL_drv.efi) $@
-$(BIN)/%.iso $(BIN)/%.usb : $(BIN)/%.efi util/genfsimg
+$(BIN)/%.iso : $(BIN)/%.efi util/genfsimg
+ $(QM)$(ECHO) " [GENFSIMG] $@"
+ $(Q)util/genfsimg -o $@ $<
+
+$(BIN)/%.usb : $(BIN)/%.efi util/genfsimg
$(QM)$(ECHO) " [GENFSIMG] $@"
$(Q)util/genfsimg -o $@ $<
diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping
index b32003ea..d13cb367 100644
--- a/src/Makefile.housekeeping
+++ b/src/Makefile.housekeeping
@@ -502,6 +502,13 @@ LDFLAGS += --gc-sections
#
LDFLAGS += -static
+# Use separate code segment if supported by linker
+#
+ZSC_TEST = $(LD) -z separate-code --version 2>&1 > /dev/null
+ZSC_FLAGS := $(shell [ -z "`$(ZSC_TEST)`" ] && \
+ $(ECHO) '-z separate-code -z max-page-size=4096')
+LDFLAGS += $(ZSC_FLAGS)
+
# compiler.h is needed for our linking and debugging system
#
CFLAGS += -include include/compiler.h
@@ -1002,6 +1009,7 @@ endif
# Device ID tables (using IDs from ROM definition file)
#
define obj_pci_id_asm
+ .section ".note.GNU-stack", "", $(ASM_TCHAR)progbits
.section ".pci_devlist.$(1)", "a", $(ASM_TCHAR)progbits
.globl pci_devlist_$(1)
pci_devlist_$(1):
@@ -1171,7 +1179,7 @@ BLIB = $(BIN)/blib.a
$(BLIB) : $(BLIB_OBJS) $(BLIB_LIST) $(MAKEDEPS)
$(Q)$(RM) $(BLIB)
$(QM)$(ECHO) " [AR] $@"
- $(Q)$(AR) rD $@ $(sort $(BLIB_OBJS))
+ $(Q)$(AR) rcD $@ $(sort $(BLIB_OBJS))
$(Q)$(OBJCOPY) --enable-deterministic-archives \
--prefix-symbols=$(SYMBOL_PREFIX) $@
$(Q)$(RANLIB) -D $@
diff --git a/src/arch/arm/Makefile b/src/arch/arm/Makefile
index 3cee5f3a..b6509dda 100644
--- a/src/arch/arm/Makefile
+++ b/src/arch/arm/Makefile
@@ -9,4 +9,5 @@ INCDIRS += arch/arm/include
# ARM-specific directories containing source files
#
+SRCDIRS += arch/arm/core
SRCDIRS += arch/arm/interface/efi
diff --git a/src/arch/arm/core/arm_io.c b/src/arch/arm/core/arm_io.c
index 1ef571fc..41b42389 100644
--- a/src/arch/arm/core/arm_io.c
+++ b/src/arch/arm/core/arm_io.c
@@ -46,7 +46,7 @@ union arm32_io_qword {
*
* This is not atomic for ARM32.
*/
-static uint64_t arm32_readq ( volatile uint64_t *io_addr ) {
+static __unused uint64_t arm32_readq ( volatile uint64_t *io_addr ) {
volatile union arm32_io_qword *ptr =
container_of ( io_addr, union arm32_io_qword, qword );
union arm32_io_qword tmp;
@@ -64,7 +64,8 @@ static uint64_t arm32_readq ( volatile uint64_t *io_addr ) {
*
* This is not atomic for ARM32.
*/
-static void arm32_writeq ( uint64_t data, volatile uint64_t *io_addr ) {
+static __unused void arm32_writeq ( uint64_t data,
+ volatile uint64_t *io_addr ) {
volatile union arm32_io_qword *ptr =
container_of ( io_addr, union arm32_io_qword, qword );
union arm32_io_qword tmp;
@@ -82,7 +83,6 @@ PROVIDE_IOAPI_INLINE ( arm, readl );
PROVIDE_IOAPI_INLINE ( arm, writeb );
PROVIDE_IOAPI_INLINE ( arm, writew );
PROVIDE_IOAPI_INLINE ( arm, writel );
-PROVIDE_IOAPI_INLINE ( arm, iodelay );
PROVIDE_IOAPI_INLINE ( arm, mb );
#ifdef __aarch64__
PROVIDE_IOAPI_INLINE ( arm, readq );
@@ -91,3 +91,4 @@ PROVIDE_IOAPI_INLINE ( arm, writeq );
PROVIDE_IOAPI ( arm, readq, arm32_readq );
PROVIDE_IOAPI ( arm, writeq, arm32_writeq );
#endif
+PROVIDE_DUMMY_PIO ( arm );
diff --git a/src/arch/arm/include/bits/pci_io.h b/src/arch/arm/include/bits/pci_io.h
index fba0eb97..91f507a4 100644
--- a/src/arch/arm/include/bits/pci_io.h
+++ b/src/arch/arm/include/bits/pci_io.h
@@ -9,6 +9,4 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-#include <ipxe/io.h>
-
#endif /* _BITS_PCI_IO_H */
diff --git a/src/arch/arm/include/ipxe/arm_io.h b/src/arch/arm/include/ipxe/arm_io.h
index 046cbdb0..7ed38993 100644
--- a/src/arch/arm/include/ipxe/arm_io.h
+++ b/src/arch/arm/include/ipxe/arm_io.h
@@ -15,6 +15,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define IOAPI_PREFIX_arm __arm_
#endif
+#include <ipxe/dummy_pio.h>
+
/*
* Memory space mappings
*
@@ -78,55 +80,6 @@ ARM_WRITEX ( l, uint32_t, "", "" );
#endif
/*
- * Dummy PIO reads and writes up to 32 bits
- *
- * There is no common standard for I/O-space access for ARM, and
- * non-MMIO peripherals are vanishingly rare. Provide dummy
- * implementations that will allow code to link and should cause
- * drivers to simply fail to detect hardware at runtime.
- *
- */
-
-#define ARM_INX( _suffix, _type ) \
-static inline __always_inline _type \
-IOAPI_INLINE ( arm, in ## _suffix ) ( volatile _type *io_addr __unused) { \
- return ~( (_type) 0 ); \
-} \
-static inline __always_inline void \
-IOAPI_INLINE ( arm, ins ## _suffix ) ( volatile _type *io_addr __unused, \
- _type *data, unsigned int count ) { \
- memset ( data, 0xff, count * sizeof ( *data ) ); \
-}
-ARM_INX ( b, uint8_t );
-ARM_INX ( w, uint16_t );
-ARM_INX ( l, uint32_t );
-
-#define ARM_OUTX( _suffix, _type ) \
-static inline __always_inline void \
-IOAPI_INLINE ( arm, out ## _suffix ) ( _type data __unused, \
- volatile _type *io_addr __unused ) { \
- /* Do nothing */ \
-} \
-static inline __always_inline void \
-IOAPI_INLINE ( arm, outs ## _suffix ) ( volatile _type *io_addr __unused, \
- const _type *data __unused, \
- unsigned int count __unused ) { \
- /* Do nothing */ \
-}
-ARM_OUTX ( b, uint8_t );
-ARM_OUTX ( w, uint16_t );
-ARM_OUTX ( l, uint32_t );
-
-/*
- * Slow down I/O
- *
- */
-static inline __always_inline void
-IOAPI_INLINE ( arm, iodelay ) ( void ) {
- /* Nothing to do */
-}
-
-/*
* Memory barrier
*
*/
@@ -140,4 +93,7 @@ IOAPI_INLINE ( arm, mb ) ( void ) {
#endif
}
+/* Dummy PIO */
+DUMMY_PIO ( arm );
+
#endif /* _IPXE_ARM_IO_H */
diff --git a/src/arch/arm64/core/setjmp.S b/src/arch/arm64/core/setjmp.S
index fa47aa0a..c5c77c1f 100644
--- a/src/arch/arm64/core/setjmp.S
+++ b/src/arch/arm64/core/setjmp.S
@@ -1,5 +1,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+ .section ".note.GNU-stack", "", %progbits
.text
/* Must match jmp_buf structure layout */
diff --git a/src/arch/i386/core/gdbidt.S b/src/arch/i386/core/gdbidt.S
index 666ecce3..78945c62 100644
--- a/src/arch/i386/core/gdbidt.S
+++ b/src/arch/i386/core/gdbidt.S
@@ -9,6 +9,7 @@
* Interrupt handlers
****************************************************************************
*/
+ .section ".note.GNU-stack", "", @progbits
.section ".text", "ax", @progbits
.code32
diff --git a/src/arch/i386/core/setjmp.S b/src/arch/i386/core/setjmp.S
index 81d3b491..e0bbb7ef 100644
--- a/src/arch/i386/core/setjmp.S
+++ b/src/arch/i386/core/setjmp.S
@@ -1,5 +1,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+ .section ".note.GNU-stack", "", @progbits
.text
.arch i386
.code32
diff --git a/src/arch/i386/tests/gdbstub_test.S b/src/arch/i386/tests/gdbstub_test.S
index 739b0527..e0c9e6c9 100644
--- a/src/arch/i386/tests/gdbstub_test.S
+++ b/src/arch/i386/tests/gdbstub_test.S
@@ -1,3 +1,4 @@
+ .section ".note.GNU-stack", "", @progbits
.arch i386
.section ".data", "aw", @progbits
diff --git a/src/arch/loong64/Makefile b/src/arch/loong64/Makefile
index f2dfc76e..fd0bf137 100644
--- a/src/arch/loong64/Makefile
+++ b/src/arch/loong64/Makefile
@@ -20,6 +20,7 @@ CFLAGS += -fshort-wchar
# LoongArch64-specific directories containing source files
SRCDIRS += arch/loong64/core
+SRCDIRS += arch/loong64/interface/efi
# Include platform-specific Makefile
MAKEDEPS += arch/loong64/Makefile.$(PLATFORM)
diff --git a/src/arch/loong64/Makefile.efi b/src/arch/loong64/Makefile.efi
new file mode 100644
index 00000000..1c51bcd6
--- /dev/null
+++ b/src/arch/loong64/Makefile.efi
@@ -0,0 +1,14 @@
+# -*- makefile -*- : Force emacs to use Makefile mode
+
+# Specify EFI image builder
+#
+ELF2EFI = $(ELF2EFI64)
+
+# Specify EFI boot file
+#
+EFI_BOOT_FILE = bootloongarch64.efi
+
+# Include generic EFI Makefile
+#
+MAKEDEPS += Makefile.efi
+include Makefile.efi
diff --git a/src/arch/loong64/core/loong64_io.c b/src/arch/loong64/core/loong64_io.c
new file mode 100644
index 00000000..6e2a78af
--- /dev/null
+++ b/src/arch/loong64/core/loong64_io.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2023, Xiaotian Wu <wuxiaotian@loongson.cn>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <ipxe/io.h>
+#include <ipxe/loong64_io.h>
+
+/** @file
+ *
+ * iPXE I/O API for LoongArch64
+ *
+ */
+
+PROVIDE_IOAPI_INLINE ( loong64, phys_to_bus );
+PROVIDE_IOAPI_INLINE ( loong64, bus_to_phys );
+PROVIDE_IOAPI_INLINE ( loong64, readb );
+PROVIDE_IOAPI_INLINE ( loong64, readw );
+PROVIDE_IOAPI_INLINE ( loong64, readl );
+PROVIDE_IOAPI_INLINE ( loong64, readq );
+PROVIDE_IOAPI_INLINE ( loong64, writeb );
+PROVIDE_IOAPI_INLINE ( loong64, writew );
+PROVIDE_IOAPI_INLINE ( loong64, writel );
+PROVIDE_IOAPI_INLINE ( loong64, writeq );
+PROVIDE_IOAPI_INLINE ( loong64, mb );
+PROVIDE_DUMMY_PIO ( loong64 );
diff --git a/src/arch/loong64/include/bits/io.h b/src/arch/loong64/include/bits/io.h
index 20ca6a7b..e9bcf2ee 100644
--- a/src/arch/loong64/include/bits/io.h
+++ b/src/arch/loong64/include/bits/io.h
@@ -12,4 +12,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** Page shift */
#define PAGE_SHIFT 12
+#include <ipxe/loong64_io.h>
+
#endif /* _BITS_IO_H */
diff --git a/src/arch/loong64/include/bits/nap.h b/src/arch/loong64/include/bits/nap.h
index 91e255d9..2deba355 100644
--- a/src/arch/loong64/include/bits/nap.h
+++ b/src/arch/loong64/include/bits/nap.h
@@ -9,4 +9,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-#endif /* _BITS_MAP_H */
+#include <ipxe/efi/efiloong64_nap.h>
+
+#endif /* _BITS_NAP_H */
diff --git a/src/arch/loong64/include/ipxe/efi/efiloong64_nap.h b/src/arch/loong64/include/ipxe/efi/efiloong64_nap.h
new file mode 100644
index 00000000..5c0d3863
--- /dev/null
+++ b/src/arch/loong64/include/ipxe/efi/efiloong64_nap.h
@@ -0,0 +1,18 @@
+#ifndef _IPXE_EFILOONG64_NAP_H
+#define _IPXE_EFILOONG64_NAP_H
+
+/** @file
+ *
+ * EFI CPU sleeping
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#ifdef NAP_EFILOONG64
+#define NAP_PREFIX_efiloong64
+#else
+#define NAP_PREFIX_efiloong64 __efiloong64_
+#endif
+
+#endif /* _IPXE_EFILOONG64_NAP_H */
diff --git a/src/arch/loong64/include/ipxe/loong64_io.h b/src/arch/loong64/include/ipxe/loong64_io.h
new file mode 100644
index 00000000..939fbf2b
--- /dev/null
+++ b/src/arch/loong64/include/ipxe/loong64_io.h
@@ -0,0 +1,82 @@
+#ifndef _IPXE_LOONG64_IO_H
+#define _IPXE_LOONG64_IO_H
+
+/** @file
+ *
+ * iPXE I/O API for LoongArch64
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#ifdef IOAPI_LOONG64
+#define IOAPI_PREFIX_loong64
+#else
+#define IOAPI_PREFIX_loong64 __loong64_
+#endif
+
+#include <ipxe/dummy_pio.h>
+
+/*
+ * Memory space mappings
+ *
+ */
+
+/*
+ * Physical<->Bus address mappings
+ *
+ */
+
+static inline __always_inline unsigned long
+IOAPI_INLINE ( loong64, phys_to_bus ) ( unsigned long phys_addr ) {
+ return phys_addr;
+}
+
+static inline __always_inline unsigned long
+IOAPI_INLINE ( loong64, bus_to_phys ) ( unsigned long bus_addr ) {
+ return bus_addr;
+}
+
+/*
+ * MMIO reads and writes up to native word size
+ *
+ */
+
+#define LOONG64_READX( _suffix, _type, _insn_suffix ) \
+static inline __always_inline _type \
+IOAPI_INLINE ( loong64, read ## _suffix ) ( volatile _type *io_addr ) { \
+ _type data; \
+ __asm__ __volatile__ ( "ld." _insn_suffix " %0, %1" \
+ : "=r" ( data ) : "m" ( *io_addr ) ); \
+ return data; \
+}
+LOONG64_READX ( b, uint8_t, "bu");
+LOONG64_READX ( w, uint16_t, "hu");
+LOONG64_READX ( l, uint32_t, "wu");
+LOONG64_READX ( q, uint64_t, "d");
+
+#define LOONG64_WRITEX( _suffix, _type, _insn_suffix ) \
+static inline __always_inline void \
+IOAPI_INLINE ( loong64, write ## _suffix ) ( _type data, \
+ volatile _type *io_addr ) { \
+ __asm__ __volatile__ ( "st." _insn_suffix " %0, %1" \
+ : : "r" ( data ), "m" ( *io_addr ) ); \
+}
+LOONG64_WRITEX ( b, uint8_t, "b");
+LOONG64_WRITEX ( w, uint16_t, "h");
+LOONG64_WRITEX ( l, uint32_t, "w" );
+LOONG64_WRITEX ( q, uint64_t, "d");
+
+/*
+ * Memory barrier
+ *
+ */
+static inline __always_inline void
+IOAPI_INLINE ( loong64, mb ) ( void ) {
+ __asm__ __volatile__ ( "dbar 0" );
+}
+
+/* Dummy PIO */
+DUMMY_PIO ( loong64 );
+
+#endif /* _IPXE_LOONG64_IO_H */
diff --git a/src/arch/loong64/interface/efi/efiloong64_nap.c b/src/arch/loong64/interface/efi/efiloong64_nap.c
new file mode 100644
index 00000000..5cd1c1b9
--- /dev/null
+++ b/src/arch/loong64/interface/efi/efiloong64_nap.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2023, Xiaotian Wu <wuxiaotian@loongson.cn>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <ipxe/nap.h>
+#include <ipxe/efi/efi.h>
+
+/** @file
+ *
+ * iPXE CPU sleeping API for EFI
+ *
+ */
+
+/**
+ * Sleep until next interrupt
+ *
+ */
+static void efiloong64_cpu_nap ( void ) {
+ /*
+ * I can't find any EFI API that allows us to put the CPU to
+ * sleep. The CpuSleep() function is defined in CpuLib.h, but
+ * isn't part of any exposed protocol so we have no way to
+ * call it.
+ *
+ * The EFI shell doesn't seem to bother sleeping the CPU; it
+ * just sits there idly burning power.
+ *
+ */
+ __asm__ __volatile__ ( "idle 0" );
+}
+
+PROVIDE_NAP ( efiloong64, cpu_nap, efiloong64_cpu_nap );
diff --git a/src/arch/x86/Makefile.pcbios b/src/arch/x86/Makefile.pcbios
index ed8d554a..38dfa087 100644
--- a/src/arch/x86/Makefile.pcbios
+++ b/src/arch/x86/Makefile.pcbios
@@ -13,6 +13,13 @@ LDSCRIPT_PREFIX = arch/x86/scripts/prefixonly.lds
#
LDFLAGS += -N --no-check-sections
+# Do not warn about RWX segments (required by most prefixes)
+#
+WRWX_TEST = $(LD) --warn-rwx-segments --version 2>&1 > /dev/null
+WRWX_FLAGS := $(shell [ -z "`$(WRWX_TEST)`" ] && \
+ $(ECHO) '--no-warn-rwx-segments')
+LDFLAGS += $(WRWX_FLAGS)
+
# Media types.
#
MEDIA += rom
@@ -54,9 +61,15 @@ LIST_NAME_mrom := ROMS
LIST_NAME_pcirom := ROMS
LIST_NAME_isarom := ROMS
-# ISO or FAT filesystem images
+# ISO images
NON_AUTO_MEDIA += iso
-$(BIN)/%.iso $(BIN)/%.sdsk: $(BIN)/%.lkrn util/genfsimg
+$(BIN)/%.iso : $(BIN)/%.lkrn util/genfsimg
+ $(QM)$(ECHO) " [GENFSIMG] $@"
+ $(Q)util/genfsimg -o $@ $<
+
+# FAT filesystem images (via syslinux)
+NON_AUTO_MEDIA += sdsk
+$(BIN)/%.sdsk : $(BIN)/%.lkrn util/genfsimg
$(QM)$(ECHO) " [GENFSIMG] $@"
$(Q)util/genfsimg -o $@ $<
diff --git a/src/arch/x86/core/patch_cf.S b/src/arch/x86/core/patch_cf.S
index 4365563f..63730c3f 100644
--- a/src/arch/x86/core/patch_cf.S
+++ b/src/arch/x86/core/patch_cf.S
@@ -22,6 +22,7 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+ .section ".note.GNU-stack", "", @progbits
.text
.arch i386
.code16
diff --git a/src/arch/x86/core/stack.S b/src/arch/x86/core/stack.S
index baa19ff8..49345347 100644
--- a/src/arch/x86/core/stack.S
+++ b/src/arch/x86/core/stack.S
@@ -1,5 +1,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+ .section ".note.GNU-stack", "", @progbits
.arch i386
#ifdef __x86_64__
diff --git a/src/arch/x86/core/stack16.S b/src/arch/x86/core/stack16.S
index ad67e4f2..d3949a55 100644
--- a/src/arch/x86/core/stack16.S
+++ b/src/arch/x86/core/stack16.S
@@ -1,5 +1,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+ .section ".note.GNU-stack", "", @progbits
.arch i386
/****************************************************************************
diff --git a/src/arch/x86/drivers/net/undiisr.S b/src/arch/x86/drivers/net/undiisr.S
index 2428d1f5..a1098b83 100644
--- a/src/arch/x86/drivers/net/undiisr.S
+++ b/src/arch/x86/drivers/net/undiisr.S
@@ -10,6 +10,7 @@ FILE_LICENCE ( GPL2_OR_LATER )
#define PIC1_ICR 0x20
#define PIC2_ICR 0xa0
+ .section ".note.GNU-stack", "", @progbits
.text
.arch i386
.code16
diff --git a/src/arch/x86/image/bzimage.c b/src/arch/x86/image/bzimage.c
index b15bd556..2c776147 100644
--- a/src/arch/x86/image/bzimage.c
+++ b/src/arch/x86/image/bzimage.c
@@ -355,6 +355,10 @@ static size_t bzimage_load_initrd ( struct image *image,
size_t offset;
size_t pad_len;
+ /* Skip hidden images */
+ if ( initrd->flags & IMAGE_HIDDEN )
+ return 0;
+
/* Create cpio header for non-prebuilt images */
offset = cpio_header ( initrd, &cpio );
diff --git a/src/arch/x86/image/multiboot.c b/src/arch/x86/image/multiboot.c
index c1c63bc9..cada021a 100644
--- a/src/arch/x86/image/multiboot.c
+++ b/src/arch/x86/image/multiboot.c
@@ -204,6 +204,10 @@ static int multiboot_add_modules ( struct image *image, physaddr_t start,
break;
}
+ /* Skip hidden images */
+ if ( module_image->flags & IMAGE_HIDDEN )
+ continue;
+
/* Page-align the module */
start = ( ( start + 0xfff ) & ~0xfff );
diff --git a/src/arch/x86/include/librm.h b/src/arch/x86/include/librm.h
index 5196d390..40f07543 100644
--- a/src/arch/x86/include/librm.h
+++ b/src/arch/x86/include/librm.h
@@ -250,8 +250,10 @@ extern void remove_user_from_rm_stack ( userptr_t data, size_t size );
/* CODE_DEFAULT: restore default .code32/.code64 directive */
#ifdef __x86_64__
#define CODE_DEFAULT ".code64"
+#define STACK_DEFAULT "q"
#else
#define CODE_DEFAULT ".code32"
+#define STACK_DEFAULT "l"
#endif
/* LINE_SYMBOL: declare a symbol for the current source code line */
@@ -268,7 +270,7 @@ extern void remove_user_from_rm_stack ( userptr_t data, size_t size );
/* REAL_CODE: declare a fragment of code that executes in real mode */
#define REAL_CODE( asm_code_str ) \
- "push $1f\n\t" \
+ "push" STACK_DEFAULT " $1f\n\t" \
"call real_call\n\t" \
TEXT16_CODE ( "\n1:\n\t" \
asm_code_str \
@@ -277,7 +279,7 @@ extern void remove_user_from_rm_stack ( userptr_t data, size_t size );
/* PHYS_CODE: declare a fragment of code that executes in flat physical mode */
#define PHYS_CODE( asm_code_str ) \
- "push $1f\n\t" \
+ "push" STACK_DEFAULT " $1f\n\t" \
"call phys_call\n\t" \
".section \".text.phys\", \"ax\", @progbits\n\t"\
"\n" LINE_SYMBOL "\n\t" \
diff --git a/src/arch/x86/interface/pcbios/bios_console.c b/src/arch/x86/interface/pcbios/bios_console.c
index 0220c856..7263eb71 100644
--- a/src/arch/x86/interface/pcbios/bios_console.c
+++ b/src/arch/x86/interface/pcbios/bios_console.c
@@ -290,29 +290,38 @@ static const char *bios_ansi_input = "";
struct bios_key {
/** Scancode */
uint8_t scancode;
- /** Key code */
- uint16_t key;
+ /** Relative key value */
+ uint16_t rkey;
} __attribute__ (( packed ));
+/**
+ * Define a BIOS key mapping
+ *
+ * @v scancode Scancode
+ * @v key iPXE key code
+ * @v bioskey BIOS key mapping
+ */
+#define BIOS_KEY( scancode, key ) { scancode, KEY_REL ( key ) }
+
/** Mapping from BIOS scan codes to iPXE key codes */
static const struct bios_key bios_keys[] = {
- { 0x53, KEY_DC },
- { 0x48, KEY_UP },
- { 0x50, KEY_DOWN },
- { 0x4b, KEY_LEFT },
- { 0x4d, KEY_RIGHT },
- { 0x47, KEY_HOME },
- { 0x4f, KEY_END },
- { 0x49, KEY_PPAGE },
- { 0x51, KEY_NPAGE },
- { 0x3f, KEY_F5 },
- { 0x40, KEY_F6 },
- { 0x41, KEY_F7 },
- { 0x42, KEY_F8 },
- { 0x43, KEY_F9 },
- { 0x44, KEY_F10 },
- { 0x85, KEY_F11 },
- { 0x86, KEY_F12 },
+ BIOS_KEY ( 0x53, KEY_DC ),
+ BIOS_KEY ( 0x48, KEY_UP ),
+ BIOS_KEY ( 0x50, KEY_DOWN ),
+ BIOS_KEY ( 0x4b, KEY_LEFT ),
+ BIOS_KEY ( 0x4d, KEY_RIGHT ),
+ BIOS_KEY ( 0x47, KEY_HOME ),
+ BIOS_KEY ( 0x4f, KEY_END ),
+ BIOS_KEY ( 0x49, KEY_PPAGE ),
+ BIOS_KEY ( 0x51, KEY_NPAGE ),
+ BIOS_KEY ( 0x3f, KEY_F5 ),
+ BIOS_KEY ( 0x40, KEY_F6 ),
+ BIOS_KEY ( 0x41, KEY_F7 ),
+ BIOS_KEY ( 0x42, KEY_F8 ),
+ BIOS_KEY ( 0x43, KEY_F9 ),
+ BIOS_KEY ( 0x44, KEY_F10 ),
+ BIOS_KEY ( 0x85, KEY_F11 ),
+ BIOS_KEY ( 0x86, KEY_F12 ),
};
/**
@@ -323,7 +332,7 @@ static const struct bios_key bios_keys[] = {
*/
static const char * bios_ansi_seq ( unsigned int scancode ) {
static char buf[ 5 /* "[" + two digits + terminator + NUL */ ];
- unsigned int key;
+ unsigned int rkey;
unsigned int terminator;
unsigned int n;
unsigned int i;
@@ -338,9 +347,9 @@ static const char * bios_ansi_seq ( unsigned int scancode ) {
continue;
/* Construct escape sequence */
- key = bios_keys[i].key;
- n = KEY_ANSI_N ( key );
- terminator = KEY_ANSI_TERMINATOR ( key );
+ rkey = bios_keys[i].rkey;
+ n = KEY_ANSI_N ( rkey );
+ terminator = KEY_ANSI_TERMINATOR ( rkey );
*(tmp++) = '[';
if ( n )
tmp += sprintf ( tmp, "%d", n );
@@ -479,6 +488,7 @@ struct console_driver bios_console __console_driver = {
static __asmcall __used void bios_inject ( struct i386_all_regs *ix86 ) {
unsigned int discard_a;
unsigned int scancode;
+ unsigned int rkey;
unsigned int i;
uint16_t keypress;
int key;
@@ -521,9 +531,10 @@ static __asmcall __used void bios_inject ( struct i386_all_regs *ix86 ) {
/* Handle special keys */
if ( key >= KEY_MIN ) {
+ rkey = KEY_REL ( key );
for ( i = 0 ; i < ( sizeof ( bios_keys ) /
sizeof ( bios_keys[0] ) ) ; i++ ) {
- if ( bios_keys[i].key == key ) {
+ if ( bios_keys[i].rkey == rkey ) {
scancode = bios_keys[i].scancode;
keypress = ( scancode << 8 );
break;
diff --git a/src/arch/x86/interface/pcbios/e820mangler.S b/src/arch/x86/interface/pcbios/e820mangler.S
index 296a6488..46e1cab4 100644
--- a/src/arch/x86/interface/pcbios/e820mangler.S
+++ b/src/arch/x86/interface/pcbios/e820mangler.S
@@ -23,6 +23,7 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+ .section ".note.GNU-stack", "", @progbits
.text
.arch i386
.code16
diff --git a/src/arch/x86/interface/pxe/pxe_call.c b/src/arch/x86/interface/pxe/pxe_call.c
index 67118299..0e8d5c5a 100644
--- a/src/arch/x86/interface/pxe/pxe_call.c
+++ b/src/arch/x86/interface/pxe/pxe_call.c
@@ -375,9 +375,10 @@ int pxe_start_nbp ( void ) {
* Notify BIOS of existence of network device
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int pxe_notify ( struct net_device *netdev ) {
+static int pxe_notify ( struct net_device *netdev, void *priv __unused ) {
/* Do nothing if we already have a network device */
if ( pxe_netdev )
diff --git a/src/arch/x86/interface/pxe/pxe_entry.S b/src/arch/x86/interface/pxe/pxe_entry.S
index 3a5a100e..354dd1b3 100644
--- a/src/arch/x86/interface/pxe/pxe_entry.S
+++ b/src/arch/x86/interface/pxe/pxe_entry.S
@@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#include <librm.h>
+ .section ".note.GNU-stack", "", @progbits
.arch i386
/****************************************************************************
diff --git a/src/arch/x86/interface/syslinux/com32_wrapper.S b/src/arch/x86/interface/syslinux/com32_wrapper.S
index d59a3392..50191956 100644
--- a/src/arch/x86/interface/syslinux/com32_wrapper.S
+++ b/src/arch/x86/interface/syslinux/com32_wrapper.S
@@ -21,6 +21,7 @@ FILE_LICENCE ( GPL2_OR_LATER )
#include "librm.h"
+ .section ".note.GNU-stack", "", @progbits
.text
.code32
diff --git a/src/arch/x86/interface/vmware/guestinfo.c b/src/arch/x86/interface/vmware/guestinfo.c
index a0530c8d..4134515c 100644
--- a/src/arch/x86/interface/vmware/guestinfo.c
+++ b/src/arch/x86/interface/vmware/guestinfo.c
@@ -207,65 +207,35 @@ struct init_fn guestinfo_init_fn __init_fn ( INIT_NORMAL ) = {
* Create per-netdevice GuestInfo settings
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int guestinfo_net_probe ( struct net_device *netdev ) {
- struct settings *settings;
+static int guestinfo_net_probe ( struct net_device *netdev, void *priv ) {
+ struct settings *settings = priv;
int rc;
/* Do nothing unless we have a GuestInfo channel available */
if ( guestinfo_channel < 0 )
return 0;
- /* Allocate and initialise settings block */
- settings = zalloc ( sizeof ( *settings ) );
- if ( ! settings ) {
- rc = -ENOMEM;
- goto err_alloc;
- }
- settings_init ( settings, &guestinfo_settings_operations, NULL, NULL );
-
- /* Register settings */
+ /* Initialise and register settings */
+ settings_init ( settings, &guestinfo_settings_operations,
+ &netdev->refcnt, NULL );
if ( ( rc = register_settings ( settings, netdev_settings ( netdev ),
"vmware" ) ) != 0 ) {
DBGC ( settings, "GuestInfo %p could not register for %s: %s\n",
settings, netdev->name, strerror ( rc ) );
- goto err_register;
+ return rc;
}
DBGC ( settings, "GuestInfo %p registered for %s\n",
settings, netdev->name );
return 0;
-
- err_register:
- free ( settings );
- err_alloc:
- return rc;
-}
-
-/**
- * Remove per-netdevice GuestInfo settings
- *
- * @v netdev Network device
- */
-static void guestinfo_net_remove ( struct net_device *netdev ) {
- struct settings *parent = netdev_settings ( netdev );
- struct settings *settings;
-
- list_for_each_entry ( settings, &parent->children, siblings ) {
- if ( settings->op == &guestinfo_settings_operations ) {
- DBGC ( settings, "GuestInfo %p unregistered for %s\n",
- settings, netdev->name );
- unregister_settings ( settings );
- free ( settings );
- return;
- }
- }
}
/** GuestInfo per-netdevice driver */
struct net_driver guestinfo_net_driver __net_driver = {
.name = "GuestInfo",
+ .priv_len = sizeof ( struct settings ),
.probe = guestinfo_net_probe,
- .remove = guestinfo_net_remove,
};
diff --git a/src/arch/x86/prefix/bootpart.S b/src/arch/x86/prefix/bootpart.S
index 6d0c6034..575cb1c0 100644
--- a/src/arch/x86/prefix/bootpart.S
+++ b/src/arch/x86/prefix/bootpart.S
@@ -5,6 +5,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define STACK_SEG 0x0200
#define STACK_SIZE 0x2000
+ .section ".note.GNU-stack", "", @progbits
.text
.arch i386
.section ".prefix", "awx", @progbits
diff --git a/src/arch/x86/prefix/dskprefix.S b/src/arch/x86/prefix/dskprefix.S
index 0503f113..bc194887 100644
--- a/src/arch/x86/prefix/dskprefix.S
+++ b/src/arch/x86/prefix/dskprefix.S
@@ -24,6 +24,7 @@ FILE_LICENCE ( GPL2_ONLY )
.equ SYSSEG, 0x1000 /* system loaded at SYSSEG<<4 */
+ .section ".note.GNU-stack", "", @progbits
.org 0
.arch i386
.text
diff --git a/src/arch/x86/prefix/exeprefix.S b/src/arch/x86/prefix/exeprefix.S
index 0eab8c12..5b2605e8 100644
--- a/src/arch/x86/prefix/exeprefix.S
+++ b/src/arch/x86/prefix/exeprefix.S
@@ -36,6 +36,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define PSP_CMDLINE_LEN 0x80
#define PSP_CMDLINE_START 0x81
+ .section ".note.GNU-stack", "", @progbits
.text
.arch i386
.org 0
diff --git a/src/arch/x86/prefix/hdprefix.S b/src/arch/x86/prefix/hdprefix.S
index 28c8a532..fbf8d2e4 100644
--- a/src/arch/x86/prefix/hdprefix.S
+++ b/src/arch/x86/prefix/hdprefix.S
@@ -2,6 +2,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#include <librm.h>
+ .section ".note.GNU-stack", "", @progbits
.text
.arch i386
.section ".prefix", "awx", @progbits
diff --git a/src/arch/x86/prefix/libprefix.S b/src/arch/x86/prefix/libprefix.S
index d7f26195..380e471d 100644
--- a/src/arch/x86/prefix/libprefix.S
+++ b/src/arch/x86/prefix/libprefix.S
@@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#include <librm.h>
+ .section ".note.GNU-stack", "", @progbits
.arch i386
/* Image compression enabled */
diff --git a/src/arch/x86/prefix/lkrnprefix.S b/src/arch/x86/prefix/lkrnprefix.S
index 922181f0..2c17f79d 100644
--- a/src/arch/x86/prefix/lkrnprefix.S
+++ b/src/arch/x86/prefix/lkrnprefix.S
@@ -4,6 +4,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define BZI_LOAD_HIGH_ADDR 0x100000
+ .section ".note.GNU-stack", "", @progbits
.text
.arch i386
.code16
diff --git a/src/arch/x86/prefix/mbr.S b/src/arch/x86/prefix/mbr.S
index 032c0e77..928bb338 100644
--- a/src/arch/x86/prefix/mbr.S
+++ b/src/arch/x86/prefix/mbr.S
@@ -1,5 +1,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+ .section ".note.GNU-stack", "", @progbits
.text
.arch i386
.section ".prefix", "awx", @progbits
diff --git a/src/arch/x86/prefix/mromprefix.S b/src/arch/x86/prefix/mromprefix.S
index d08284d7..5f3496b2 100644
--- a/src/arch/x86/prefix/mromprefix.S
+++ b/src/arch/x86/prefix/mromprefix.S
@@ -41,6 +41,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define _pcirom_start _mrom_start
#include "pciromprefix.S"
+ .section ".note.GNU-stack", "", @progbits
.text
.arch i386
.code16
diff --git a/src/arch/x86/prefix/nbiprefix.S b/src/arch/x86/prefix/nbiprefix.S
index de38e4af..cae1009b 100644
--- a/src/arch/x86/prefix/nbiprefix.S
+++ b/src/arch/x86/prefix/nbiprefix.S
@@ -2,6 +2,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#include <librm.h>
+ .section ".note.GNU-stack", "", @progbits
.text
.arch i386
.code16
diff --git a/src/arch/x86/prefix/nullprefix.S b/src/arch/x86/prefix/nullprefix.S
index bd0ff339..1568188d 100644
--- a/src/arch/x86/prefix/nullprefix.S
+++ b/src/arch/x86/prefix/nullprefix.S
@@ -1,5 +1,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+ .section ".note.GNU-stack", "", @progbits
.org 0
.text
.arch i386
diff --git a/src/arch/x86/prefix/pxeprefix.S b/src/arch/x86/prefix/pxeprefix.S
index 52ea1803..494fbc13 100644
--- a/src/arch/x86/prefix/pxeprefix.S
+++ b/src/arch/x86/prefix/pxeprefix.S
@@ -11,6 +11,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define PXE_HACK_EB54 0x0001
+ .section ".note.GNU-stack", "", @progbits
.text
.arch i386
.org 0
diff --git a/src/arch/x86/prefix/rawprefix.S b/src/arch/x86/prefix/rawprefix.S
index 4cf5f391..4a3d3504 100644
--- a/src/arch/x86/prefix/rawprefix.S
+++ b/src/arch/x86/prefix/rawprefix.S
@@ -8,6 +8,7 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+ .section ".note.GNU-stack", "", @progbits
.text
.arch i386
.org 0
diff --git a/src/arch/x86/prefix/romprefix.S b/src/arch/x86/prefix/romprefix.S
index 4e8793c2..79fed2a3 100644
--- a/src/arch/x86/prefix/romprefix.S
+++ b/src/arch/x86/prefix/romprefix.S
@@ -54,6 +54,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define BUSTYPE "PCIR"
#endif
+ .section ".note.GNU-stack", "", @progbits
.text
.code16
.arch i386
diff --git a/src/arch/x86/prefix/undiloader.S b/src/arch/x86/prefix/undiloader.S
index 1d77110e..e544d504 100644
--- a/src/arch/x86/prefix/undiloader.S
+++ b/src/arch/x86/prefix/undiloader.S
@@ -2,6 +2,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#include <librm.h>
+ .section ".note.GNU-stack", "", @progbits
.text
.code16
.arch i386
diff --git a/src/arch/x86/prefix/unlzma.S b/src/arch/x86/prefix/unlzma.S
index 979f699e..f4bd81bd 100644
--- a/src/arch/x86/prefix/unlzma.S
+++ b/src/arch/x86/prefix/unlzma.S
@@ -43,6 +43,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
****************************************************************************
*/
+ .section ".note.GNU-stack", "", @progbits
.text
.arch i486
.section ".prefix.lib", "ax", @progbits
diff --git a/src/arch/x86/prefix/usbdisk.S b/src/arch/x86/prefix/usbdisk.S
index 977de6dd..461a0837 100644
--- a/src/arch/x86/prefix/usbdisk.S
+++ b/src/arch/x86/prefix/usbdisk.S
@@ -2,6 +2,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#include <config/console.h>
+ .section ".note.GNU-stack", "", @progbits
.text
.arch i386
.section ".prefix", "awx", @progbits
diff --git a/src/arch/x86/transitions/liba20.S b/src/arch/x86/transitions/liba20.S
index 57603353..6c1bac67 100644
--- a/src/arch/x86/transitions/liba20.S
+++ b/src/arch/x86/transitions/liba20.S
@@ -24,6 +24,7 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+ .section ".note.GNU-stack", "", @progbits
.arch i386
/****************************************************************************
diff --git a/src/arch/x86/transitions/libkir.S b/src/arch/x86/transitions/libkir.S
index fa9459d5..af090b26 100644
--- a/src/arch/x86/transitions/libkir.S
+++ b/src/arch/x86/transitions/libkir.S
@@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
/* Breakpoint for when debugging under bochs */
#define BOCHSBP xchgw %bx, %bx
+ .section ".note.GNU-stack", "", @progbits
.text
.arch i386
.section ".text16", "awx", @progbits
diff --git a/src/arch/x86/transitions/librm.S b/src/arch/x86/transitions/librm.S
index 5dacb9b0..39431324 100644
--- a/src/arch/x86/transitions/librm.S
+++ b/src/arch/x86/transitions/librm.S
@@ -83,6 +83,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define if64 if 0
#endif
+ .section ".note.GNU-stack", "", @progbits
+
/****************************************************************************
* Global descriptor table
*
diff --git a/src/arch/x86_64/core/gdbidt.S b/src/arch/x86_64/core/gdbidt.S
index 89280bf8..477492b4 100644
--- a/src/arch/x86_64/core/gdbidt.S
+++ b/src/arch/x86_64/core/gdbidt.S
@@ -38,6 +38,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define SIGFPE 8
#define SIGSTKFLT 16
+ .section ".note.GNU-stack", "", @progbits
.section ".text.gdbmach_interrupt", "ax", @progbits
.code64
diff --git a/src/arch/x86_64/core/setjmp.S b/src/arch/x86_64/core/setjmp.S
index e43200d7..5137a72c 100644
--- a/src/arch/x86_64/core/setjmp.S
+++ b/src/arch/x86_64/core/setjmp.S
@@ -1,5 +1,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+ .section ".note.GNU-stack", "", @progbits
.text
.code64
diff --git a/src/config/config.c b/src/config/config.c
index a8186613..abb7d16a 100644
--- a/src/config/config.c
+++ b/src/config/config.c
@@ -290,6 +290,9 @@ REQUIRE_OBJECT ( cert_cmd );
#ifdef IMAGE_MEM_CMD
REQUIRE_OBJECT ( image_mem_cmd );
#endif
+#ifdef SHIM_CMD
+REQUIRE_OBJECT ( shim_cmd );
+#endif
/*
* Drag in miscellaneous objects
@@ -352,6 +355,9 @@ REQUIRE_OBJECT ( vram_settings );
#ifdef ACPI_SETTINGS
REQUIRE_OBJECT ( acpi_settings );
#endif
+#ifdef EFI_SETTINGS
+REQUIRE_OBJECT ( efi_settings );
+#endif
/*
* Drag in selected keyboard map
diff --git a/src/config/defaults/efi.h b/src/config/defaults/efi.h
index 8e53b9ab..e39d475b 100644
--- a/src/config/defaults/efi.h
+++ b/src/config/defaults/efi.h
@@ -48,6 +48,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define REBOOT_CMD /* Reboot command */
+#define EFI_SETTINGS /* EFI variable settings */
+
#if defined ( __i386__ ) || defined ( __x86_64__ )
#define IOAPI_X86
#define NAP_EFIX86
@@ -65,4 +67,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define IMAGE_GZIP /* GZIP image support */
#endif
+#if defined ( __loongarch__ )
+#define IOAPI_LOONG64
+#define NAP_EFILOONG64
+#endif
+
#endif /* CONFIG_DEFAULTS_EFI_H */
diff --git a/src/config/general.h b/src/config/general.h
index 51ccaeaa..fff4b392 100644
--- a/src/config/general.h
+++ b/src/config/general.h
@@ -161,6 +161,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
//#define IMAGE_MEM_CMD /* Read memory command */
#define IMAGE_ARCHIVE_CMD /* Archive image management commands */
#define EFIMAP_CMD /* EFI Map command */
+#define SHIM_CMD /* EFI shim command (or dummy command) */
/*
* ROM-specific options
diff --git a/src/config/settings.h b/src/config/settings.h
index d9c86a38..d7f787d3 100644
--- a/src/config/settings.h
+++ b/src/config/settings.h
@@ -9,6 +9,8 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+#include <config/defaults.h>
+
#define PCI_SETTINGS /* PCI device settings */
//#define CPUID_SETTINGS /* CPUID settings */
//#define MEMMAP_SETTINGS /* Memory map settings */
diff --git a/src/core/cachedhcp.c b/src/core/cachedhcp.c
index 60213f02..57226e16 100644
--- a/src/core/cachedhcp.c
+++ b/src/core/cachedhcp.c
@@ -295,9 +295,10 @@ struct startup_fn cachedhcp_startup_fn __startup_fn ( STARTUP_LATE ) = {
* Apply cached DHCPACK to network device, if applicable
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int cachedhcp_probe ( struct net_device *netdev ) {
+static int cachedhcp_probe ( struct net_device *netdev, void *priv __unused ) {
/* Apply cached DHCPACK to network device, if applicable */
return cachedhcp_apply ( &cached_dhcpack, netdev );
diff --git a/src/core/image.c b/src/core/image.c
index b280eb4d..3e65b5ed 100644
--- a/src/core/image.c
+++ b/src/core/image.c
@@ -56,8 +56,15 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** List of registered images */
struct list_head images = LIST_HEAD_INIT ( images );
+/** Image selected for execution */
+struct image_tag selected_image __image_tag = {
+ .name = "SELECTED",
+};
+
/** Currently-executing image */
-struct image *current_image;
+struct image_tag current_image __image_tag = {
+ .name = "CURRENT",
+};
/** Current image trust requirement */
static int require_trusted_images = 0;
@@ -72,8 +79,13 @@ static int require_trusted_images_permanent = 0;
*/
static void free_image ( struct refcnt *refcnt ) {
struct image *image = container_of ( refcnt, struct image, refcnt );
+ struct image_tag *tag;
DBGC ( image, "IMAGE %s freed\n", image->name );
+ for_each_table_entry ( tag, IMAGE_TAGS ) {
+ if ( tag->image == image )
+ tag->image = NULL;
+ }
free ( image->name );
free ( image->cmdline );
uri_put ( image->uri );
@@ -261,12 +273,6 @@ int register_image ( struct image *image ) {
return rc;
}
- /* Avoid ending up with multiple "selected" images on
- * re-registration
- */
- if ( image_find_selected() )
- image->flags &= ~IMAGE_SELECTED;
-
/* Add to image list */
image_get ( image );
image->flags |= IMAGE_REGISTERED;
@@ -321,6 +327,23 @@ struct image * find_image ( const char *name ) {
}
/**
+ * Find image by tag
+ *
+ * @v tag Image tag
+ * @ret image Executable image, or NULL
+ */
+struct image * find_image_tag ( struct image_tag *tag ) {
+ struct image *image;
+
+ for_each_image ( image ) {
+ if ( tag->image == image )
+ return image;
+ }
+
+ return NULL;
+}
+
+/**
* Execute image
*
* @v image Executable image
@@ -346,13 +369,13 @@ int image_exec ( struct image *image ) {
if ( image->uri )
churi ( image->uri );
- /* Preserve record of any currently-running image */
- saved_current_image = current_image;
+ /* Set as currently running image */
+ saved_current_image = image_tag ( image, &current_image );
/* Take out a temporary reference to the image, so that it
* does not get freed when temporarily unregistered.
*/
- current_image = image_get ( image );
+ image_get ( image );
/* Check that this image can be executed */
if ( ! ( image->type && image->type->exec ) ) {
@@ -419,7 +442,7 @@ int image_exec ( struct image *image ) {
image_put ( image );
/* Restore previous currently-running image */
- current_image = saved_current_image;
+ image_tag ( saved_current_image, &current_image );
/* Reset current working directory */
churi ( old_cwuri );
@@ -442,7 +465,7 @@ int image_exec ( struct image *image ) {
* registered until the currently-executing image returns.
*/
int image_replace ( struct image *replacement ) {
- struct image *image = current_image;
+ struct image *image = current_image.image;
int rc;
/* Sanity check */
@@ -478,38 +501,18 @@ int image_replace ( struct image *replacement ) {
* @ret rc Return status code
*/
int image_select ( struct image *image ) {
- struct image *tmp;
-
- /* Unselect all other images */
- for_each_image ( tmp )
- tmp->flags &= ~IMAGE_SELECTED;
/* Check that this image can be executed */
if ( ! ( image->type && image->type->exec ) )
return -ENOEXEC;
/* Mark image as selected */
- image->flags |= IMAGE_SELECTED;
+ image_tag ( image, &selected_image );
return 0;
}
/**
- * Find selected image
- *
- * @ret image Executable image, or NULL
- */
-struct image * image_find_selected ( void ) {
- struct image *image;
-
- for_each_image ( image ) {
- if ( image->flags & IMAGE_SELECTED )
- return image;
- }
- return NULL;
-}
-
-/**
* Change image trust requirement
*
* @v require_trusted Require trusted images
diff --git a/src/core/interface.c b/src/core/interface.c
index 34a4180a..ea060689 100644
--- a/src/core/interface.c
+++ b/src/core/interface.c
@@ -285,6 +285,7 @@ void intf_shutdown ( struct interface *intf, int rc ) {
intf_nullify ( intf );
/* Transfer destination to temporary interface */
+ intf_temp_init ( &tmp, intf );
tmp.dest = intf->dest;
intf->dest = &null_intf;
diff --git a/src/core/parseopt.c b/src/core/parseopt.c
index 1dbfc7ae..cd3b3101 100644
--- a/src/core/parseopt.c
+++ b/src/core/parseopt.c
@@ -28,6 +28,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <ipxe/netdevice.h>
@@ -35,6 +36,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/settings.h>
#include <ipxe/params.h>
#include <ipxe/timer.h>
+#include <ipxe/keys.h>
#include <ipxe/parseopt.h>
#include <config/branding.h>
@@ -213,6 +215,7 @@ int parse_flag ( char *text __unused, int *flag ) {
* @ret rc Return status code
*/
int parse_key ( char *text, unsigned int *key ) {
+ int rc;
/* Interpret single characters as being a literal key character */
if ( text[0] && ! text[1] ) {
@@ -221,7 +224,17 @@ int parse_key ( char *text, unsigned int *key ) {
}
/* Otherwise, interpret as an integer */
- return parse_integer ( text, key );
+ if ( ( rc = parse_integer ( text, key ) ) < 0 )
+ return rc;
+
+ /* For backwards compatibility with existing scripts, treat
+ * integers between the ASCII range and special key range as
+ * being relative special key values.
+ */
+ if ( ( ! isascii ( *key ) ) && ( *key < KEY_MIN ) )
+ *key += KEY_MIN;
+
+ return 0;
}
/**
diff --git a/src/core/random.c b/src/core/random.c
index 975a03cf..e3251964 100644
--- a/src/core/random.c
+++ b/src/core/random.c
@@ -6,8 +6,9 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+#include <stddef.h>
#include <stdlib.h>
-#include <ipxe/timer.h>
+#include <time.h>
static int32_t rnd_seed = 0;
@@ -30,8 +31,9 @@ void srandom ( unsigned int seed ) {
long int random ( void ) {
int32_t q;
- if ( ! rnd_seed ) /* Initialize linear congruential generator */
- srandom ( currticks() );
+ /* Initialize linear congruential generator */
+ if ( ! rnd_seed )
+ srandom ( time ( NULL ) );
/* simplified version of the LCG given in Bruce Schneier's
"Applied Cryptography" */
diff --git a/src/core/xfer.c b/src/core/xfer.c
index 0faf3292..269359e1 100644
--- a/src/core/xfer.c
+++ b/src/core/xfer.c
@@ -60,7 +60,7 @@ static struct xfer_metadata dummy_metadata;
* @ret rc Return status code
*/
int xfer_vredirect ( struct interface *intf, int type, va_list args ) {
- struct interface tmp = INTF_INIT ( null_intf_desc );
+ struct interface tmp;
struct interface *dest;
xfer_vredirect_TYPE ( void * ) *op =
intf_get_dest_op_no_passthru ( intf, xfer_vredirect, &dest );
@@ -85,6 +85,7 @@ int xfer_vredirect ( struct interface *intf, int type, va_list args ) {
* If redirection fails, then send intf_close() to the
* parent interface.
*/
+ intf_temp_init ( &tmp, intf );
intf_plug ( &tmp, dest );
rc = xfer_vreopen ( dest, type, args );
if ( rc == 0 ) {
diff --git a/src/crypto/asn1.c b/src/crypto/asn1.c
index 549ee4d8..dc9d1c54 100644
--- a/src/crypto/asn1.c
+++ b/src/crypto/asn1.c
@@ -590,6 +590,32 @@ int asn1_signature_algorithm ( const struct asn1_cursor *cursor,
}
/**
+ * Check ASN.1 OID-identified algorithm
+ *
+ * @v cursor ASN.1 object cursor
+ * @v expected Expected algorithm
+ * @ret rc Return status code
+ */
+int asn1_check_algorithm ( const struct asn1_cursor *cursor,
+ struct asn1_algorithm *expected ) {
+ struct asn1_algorithm *actual;
+ int rc;
+
+ /* Parse algorithm */
+ if ( ( rc = asn1_algorithm ( cursor, &actual ) ) != 0 )
+ return rc;
+
+ /* Check algorithm matches */
+ if ( actual != expected ) {
+ DBGC ( cursor, "ASN1 %p algorithm %s does not match %s\n",
+ cursor, actual->name, expected->name );
+ return -ENOTTY_ALGORITHM;
+ }
+
+ return 0;
+}
+
+/**
* Parse ASN.1 GeneralizedTime
*
* @v cursor ASN.1 cursor
diff --git a/src/crypto/rsa.c b/src/crypto/rsa.c
index a3895574..16c67d82 100644
--- a/src/crypto/rsa.c
+++ b/src/crypto/rsa.c
@@ -164,7 +164,7 @@ static int rsa_parse_mod_exp ( struct asn1_cursor *modulus,
int is_private;
int rc;
- /* Enter subjectPublicKeyInfo/RSAPrivateKey */
+ /* Enter subjectPublicKeyInfo/privateKeyInfo/RSAPrivateKey */
memcpy ( &cursor, raw, sizeof ( cursor ) );
asn1_enter ( &cursor, ASN1_SEQUENCE );
@@ -177,6 +177,23 @@ static int rsa_parse_mod_exp ( struct asn1_cursor *modulus,
/* Skip version */
asn1_skip_any ( &cursor );
+ /* Enter privateKey, if present */
+ if ( asn1_check_algorithm ( &cursor,
+ &rsa_encryption_algorithm ) == 0 ) {
+
+ /* Skip privateKeyAlgorithm */
+ asn1_skip_any ( &cursor );
+
+ /* Enter privateKey */
+ asn1_enter ( &cursor, ASN1_OCTET_STRING );
+
+ /* Enter RSAPrivateKey */
+ asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+ /* Skip version */
+ asn1_skip ( &cursor, ASN1_INTEGER );
+ }
+
} else {
/* Public key */
diff --git a/src/drivers/bus/virtio-pci.c b/src/drivers/bus/virtio-pci.c
index 8b34c727..3fc93a90 100644
--- a/src/drivers/bus/virtio-pci.c
+++ b/src/drivers/bus/virtio-pci.c
@@ -230,10 +230,10 @@ u32 vpm_ioread32(struct virtio_pci_modern_device *vdev,
uint32_t data;
switch (region->flags & VIRTIO_PCI_REGION_TYPE_MASK) {
case VIRTIO_PCI_REGION_MEMORY:
- data = readw(region->base + offset);
+ data = readl(region->base + offset);
break;
case VIRTIO_PCI_REGION_PORT:
- data = inw(region->base + offset);
+ data = inl(region->base + offset);
break;
case VIRTIO_PCI_REGION_PCI_CONFIG:
prep_pci_cfg_cap(vdev, region, offset, 4);
diff --git a/src/drivers/linux/af_packet.c b/src/drivers/linux/af_packet.c
index 9fa6ef2a..980bd462 100644
--- a/src/drivers/linux/af_packet.c
+++ b/src/drivers/linux/af_packet.c
@@ -300,9 +300,9 @@ static int af_packet_nic_probe ( struct linux_device *device,
return 0;
-err_settings:
unregister_netdev(netdev);
err_register:
+err_settings:
netdev_nullify(netdev);
netdev_put(netdev);
return rc;
diff --git a/src/drivers/linux/tap.c b/src/drivers/linux/tap.c
index ff1e08bd..c1364ddb 100644
--- a/src/drivers/linux/tap.c
+++ b/src/drivers/linux/tap.c
@@ -56,6 +56,10 @@ struct tap_nic {
int fd;
};
+/** Default MAC address */
+static const uint8_t tap_default_mac[ETH_ALEN] =
+ { 0x52, 0x54, 0x00, 0x12, 0x34, 0x56 };
+
/** Open the TAP device */
static int tap_open(struct net_device * netdev)
{
@@ -202,6 +206,7 @@ static int tap_probe(struct linux_device *device, struct linux_device_request *r
nic = netdev->priv;
linux_set_drvdata(device, netdev);
netdev->dev = &device->dev;
+ memcpy ( netdev->hw_addr, tap_default_mac, ETH_ALEN );
memset(nic, 0, sizeof(*nic));
/* Look for the mandatory if setting */
@@ -231,9 +236,9 @@ static int tap_probe(struct linux_device *device, struct linux_device_request *r
return 0;
-err_settings:
unregister_netdev(netdev);
err_register:
+err_settings:
netdev_nullify(netdev);
netdev_put(netdev);
return rc;
diff --git a/src/drivers/net/3c90x.c b/src/drivers/net/3c90x.c
index 63e07777..1b8190c4 100644
--- a/src/drivers/net/3c90x.c
+++ b/src/drivers/net/3c90x.c
@@ -272,7 +272,7 @@ static int a3c90x_setup_tx_ring(struct INF_3C90X *p)
*/
static void a3c90x_process_tx_packets(struct net_device *netdev)
{
- struct INF_3C90X *p = netdev_priv(netdev);
+ struct INF_3C90X *p = netdev->priv;
unsigned int downlist_ptr;
DBGP("a3c90x_process_tx_packets\n");
@@ -320,7 +320,7 @@ static void a3c90x_free_tx_ring(struct INF_3C90X *p)
static int a3c90x_transmit(struct net_device *netdev,
struct io_buffer *iob)
{
- struct INF_3C90X *inf_3c90x = netdev_priv(netdev);
+ struct INF_3C90X *inf_3c90x = netdev->priv;
struct TXD *tx_cur_desc;
struct TXD *tx_prev_desc;
@@ -518,7 +518,7 @@ static void a3c90x_process_rx_packets(struct net_device *netdev)
{
int i;
unsigned int rx_status;
- struct INF_3C90X *p = netdev_priv(netdev);
+ struct INF_3C90X *p = netdev->priv;
struct RXD *rx_cur_desc;
DBGP("a3c90x_process_rx_packets\n");
@@ -567,7 +567,7 @@ static void a3c90x_process_rx_packets(struct net_device *netdev)
*/
static void a3c90x_poll(struct net_device *netdev)
{
- struct INF_3C90X *p = netdev_priv(netdev);
+ struct INF_3C90X *p = netdev->priv;
uint16_t raw_status, int_status;
DBGP("a3c90x_poll\n");
@@ -611,7 +611,7 @@ static void a3c90x_free_resources(struct INF_3C90X *p)
static void a3c90x_remove(struct pci_device *pci)
{
struct net_device *netdev = pci_get_drvdata(pci);
- struct INF_3C90X *inf_3c90x = netdev_priv(netdev);
+ struct INF_3C90X *inf_3c90x = netdev->priv;
DBGP("a3c90x_remove\n");
@@ -628,7 +628,7 @@ static void a3c90x_remove(struct pci_device *pci)
static void a3c90x_irq(struct net_device *netdev, int enable)
{
- struct INF_3C90X *p = netdev_priv(netdev);
+ struct INF_3C90X *p = netdev->priv;
DBGP("a3c90x_irq\n");
@@ -657,7 +657,7 @@ static void a3c90x_hw_start(struct net_device *netdev)
unsigned int cfg;
unsigned int mopt;
unsigned short linktype;
- struct INF_3C90X *inf_3c90x = netdev_priv(netdev);
+ struct INF_3C90X *inf_3c90x = netdev->priv;
DBGP("a3c90x_hw_start\n");
@@ -796,7 +796,7 @@ static void a3c90x_hw_start(struct net_device *netdev)
static int a3c90x_open(struct net_device *netdev)
{
int rc;
- struct INF_3C90X *inf_3c90x = netdev_priv(netdev);
+ struct INF_3C90X *inf_3c90x = netdev->priv;
DBGP("a3c90x_open\n");
@@ -845,7 +845,7 @@ static int a3c90x_open(struct net_device *netdev)
*/
static void a3c90x_close(struct net_device *netdev)
{
- struct INF_3C90X *inf_3c90x = netdev_priv(netdev);
+ struct INF_3C90X *inf_3c90x = netdev->priv;
DBGP("a3c90x_close\n");
@@ -895,7 +895,7 @@ static int a3c90x_probe(struct pci_device *pci)
pci_set_drvdata(pci, netdev);
netdev->dev = &pci->dev;
- inf_3c90x = netdev_priv(netdev);
+ inf_3c90x = netdev->priv;
memset(inf_3c90x, 0, sizeof(*inf_3c90x));
adjust_pci_device(pci);
diff --git a/src/drivers/net/atl1e.c b/src/drivers/net/atl1e.c
index 0f0df532..1acbb3ca 100644
--- a/src/drivers/net/atl1e.c
+++ b/src/drivers/net/atl1e.c
@@ -173,7 +173,7 @@ static int atl1e_check_link(struct atl1e_adapter *adapter)
static int atl1e_mdio_read(struct net_device *netdev, int phy_id __unused,
int reg_num)
{
- struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_adapter *adapter = netdev->priv;
u16 result;
atl1e_read_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, &result);
@@ -183,7 +183,7 @@ static int atl1e_mdio_read(struct net_device *netdev, int phy_id __unused,
static void atl1e_mdio_write(struct net_device *netdev, int phy_id __unused,
int reg_num, int val)
{
- struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_adapter *adapter = netdev->priv;
atl1e_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val);
}
@@ -841,7 +841,7 @@ fatal_err:
*/
static void atl1e_poll(struct net_device *netdev)
{
- struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_adapter *adapter = netdev->priv;
struct atl1e_hw *hw = &adapter->hw;
int max_ints = 64;
u32 status;
@@ -963,7 +963,7 @@ static void atl1e_tx_queue(struct atl1e_adapter *adapter, u16 count __unused,
static int atl1e_xmit_frame(struct net_device *netdev, struct io_buffer *iob)
{
- struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_adapter *adapter = netdev->priv;
u16 tpd_req = 1;
struct atl1e_tpd_desc *tpd;
@@ -1013,7 +1013,7 @@ int atl1e_up(struct atl1e_adapter *adapter)
void atl1e_irq(struct net_device *netdev, int enable)
{
- struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_adapter *adapter = netdev->priv;
if (enable)
atl1e_irq_enable(adapter);
@@ -1051,7 +1051,7 @@ void atl1e_down(struct atl1e_adapter *adapter)
*/
static int atl1e_open(struct net_device *netdev)
{
- struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_adapter *adapter = netdev->priv;
int err;
/* allocate rx/tx dma buffer & descriptors */
@@ -1086,7 +1086,7 @@ err_up:
*/
static void atl1e_close(struct net_device *netdev)
{
- struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_adapter *adapter = netdev->priv;
atl1e_down(adapter);
atl1e_free_ring_resources(adapter);
@@ -1138,7 +1138,7 @@ static int atl1e_probe(struct pci_device *pdev)
atl1e_init_netdev(netdev, pdev);
- adapter = netdev_priv(netdev);
+ adapter = netdev->priv;
adapter->bd_number = cards_found;
adapter->netdev = netdev;
adapter->pdev = pdev;
@@ -1227,7 +1227,7 @@ err:
static void atl1e_remove(struct pci_device *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_adapter *adapter = netdev->priv;
unregister_netdev(netdev);
atl1e_free_ring_resources(adapter);
diff --git a/src/drivers/net/b44.c b/src/drivers/net/b44.c
index eaf6d35c..1ca7e2e5 100644
--- a/src/drivers/net/b44.c
+++ b/src/drivers/net/b44.c
@@ -622,7 +622,7 @@ static void b44_load_mac_and_phy_addr(struct b44_private *bp)
static void b44_set_rx_mode(struct net_device *netdev)
{
- struct b44_private *bp = netdev_priv(netdev);
+ struct b44_private *bp = netdev->priv;
unsigned char zero[6] = { 0, 0, 0, 0, 0, 0 };
u32 val;
int i;
@@ -667,7 +667,7 @@ static int b44_probe(struct pci_device *pci)
netdev->dev = &pci->dev;
/* Set up private data */
- bp = netdev_priv(netdev);
+ bp = netdev->priv;
memset(bp, 0, sizeof(*bp));
bp->netdev = netdev;
bp->pci = pci;
@@ -712,7 +712,7 @@ static int b44_probe(struct pci_device *pci)
static void b44_remove(struct pci_device *pci)
{
struct net_device *netdev = pci_get_drvdata(pci);
- struct b44_private *bp = netdev_priv(netdev);
+ struct b44_private *bp = netdev->priv;
ssb_core_disable(bp);
unregister_netdev(netdev);
@@ -729,7 +729,7 @@ static void b44_remove(struct pci_device *pci)
*/
static void b44_irq(struct net_device *netdev, int enable)
{
- struct b44_private *bp = netdev_priv(netdev);
+ struct b44_private *bp = netdev->priv;
/* Interrupt mask specifies which events generate interrupts */
bw32(bp, B44_IMASK, enable ? IMASK_DEF : IMASK_DISABLE);
@@ -743,7 +743,7 @@ static void b44_irq(struct net_device *netdev, int enable)
*/
static int b44_open(struct net_device *netdev)
{
- struct b44_private *bp = netdev_priv(netdev);
+ struct b44_private *bp = netdev->priv;
int rc;
rc = b44_init_tx_ring(bp);
@@ -769,7 +769,7 @@ static int b44_open(struct net_device *netdev)
*/
static void b44_close(struct net_device *netdev)
{
- struct b44_private *bp = netdev_priv(netdev);
+ struct b44_private *bp = netdev->priv;
b44_chip_reset(bp, B44_FULL_RESET);
b44_free_tx_ring(bp);
@@ -785,7 +785,7 @@ static void b44_close(struct net_device *netdev)
*/
static int b44_transmit(struct net_device *netdev, struct io_buffer *iobuf)
{
- struct b44_private *bp = netdev_priv(netdev);
+ struct b44_private *bp = netdev->priv;
u32 cur = bp->tx_cur;
u32 ctrl;
@@ -905,7 +905,7 @@ static void b44_process_rx_packets(struct b44_private *bp)
*/
static void b44_poll(struct net_device *netdev)
{
- struct b44_private *bp = netdev_priv(netdev);
+ struct b44_private *bp = netdev->priv;
u32 istat;
/* Interrupt status */
diff --git a/src/drivers/net/bnxt/bnxt.c b/src/drivers/net/bnxt/bnxt.c
index e3876503..605aea32 100644
--- a/src/drivers/net/bnxt/bnxt.c
+++ b/src/drivers/net/bnxt/bnxt.c
@@ -307,7 +307,7 @@ void bnxt_set_txq ( struct bnxt *bp, int entry, dma_addr_t mapping, int len )
static void bnxt_tx_complete ( struct net_device *dev, u16 hw_idx )
{
- struct bnxt *bp = netdev_priv ( dev );
+ struct bnxt *bp = dev->priv;
struct io_buffer *iob;
iob = bp->tx.iob[hw_idx];
@@ -484,7 +484,7 @@ void bnxt_rx_process ( struct net_device *dev, struct bnxt *bp,
static int bnxt_rx_complete ( struct net_device *dev,
struct rx_pkt_cmpl *rx_cmp )
{
- struct bnxt *bp = netdev_priv ( dev );
+ struct bnxt *bp = dev->priv;
struct rx_pkt_cmpl_hi *rx_cmp_hi;
u8 cmpl_bit = bp->cq.completion_bit;
@@ -1927,7 +1927,7 @@ int bnxt_hwrm_run ( hwrm_func_t cmds[], struct bnxt *bp )
static int bnxt_open ( struct net_device *dev )
{
- struct bnxt *bp = netdev_priv ( dev );
+ struct bnxt *bp = dev->priv;
DBGP ( "%s\n", __func__ );
bnxt_mm_nic ( bp );
@@ -1952,7 +1952,7 @@ static void bnxt_tx_adjust_pkt ( struct bnxt *bp, struct io_buffer *iob )
static int bnxt_tx ( struct net_device *dev, struct io_buffer *iob )
{
- struct bnxt *bp = netdev_priv ( dev );
+ struct bnxt *bp = dev->priv;
u16 len, entry;
dma_addr_t mapping;
@@ -2009,7 +2009,7 @@ void bnxt_link_evt ( struct bnxt *bp, struct hwrm_async_event_cmpl *evt )
static void bnxt_service_cq ( struct net_device *dev )
{
- struct bnxt *bp = netdev_priv ( dev );
+ struct bnxt *bp = dev->priv;
struct cmpl_base *cmp;
struct tx_cmpl *tx;
u16 old_cid = bp->cq.cons_id;
@@ -2057,7 +2057,7 @@ static void bnxt_service_cq ( struct net_device *dev )
static void bnxt_service_nq ( struct net_device *dev )
{
- struct bnxt *bp = netdev_priv ( dev );
+ struct bnxt *bp = dev->priv;
struct nq_base *nqp;
u16 old_cid = bp->nq.cons_id;
int done = SERVICE_NEXT_NQ_BD;
@@ -2102,7 +2102,7 @@ static void bnxt_poll ( struct net_device *dev )
static void bnxt_close ( struct net_device *dev )
{
- struct bnxt *bp = netdev_priv ( dev );
+ struct bnxt *bp = dev->priv;
DBGP ( "%s\n", __func__ );
bnxt_down_nic (bp);
@@ -2143,7 +2143,7 @@ static int bnxt_init_one ( struct pci_device *pci )
netdev_init ( netdev, &bnxt_netdev_ops );
/* Driver private area for this device */
- bp = netdev_priv ( netdev );
+ bp = netdev->priv;
/* Set PCI driver private data */
pci_set_drvdata ( pci, netdev );
@@ -2197,7 +2197,7 @@ disable_pdev:
static void bnxt_remove_one ( struct pci_device *pci )
{
struct net_device *netdev = pci_get_drvdata ( pci );
- struct bnxt *bp = netdev_priv ( netdev );
+ struct bnxt *bp = netdev->priv;
DBGP ( "%s\n", __func__ );
/* Unregister network device */
diff --git a/src/drivers/net/eepro100.c b/src/drivers/net/eepro100.c
index 1a802b59..a0551a89 100644
--- a/src/drivers/net/eepro100.c
+++ b/src/drivers/net/eepro100.c
@@ -690,7 +690,7 @@ static void ifec_reset ( struct net_device *netdev )
*/
static void ifec_free ( struct net_device *netdev )
{
- struct ifec_private *priv = netdev_priv ( netdev );
+ struct ifec_private *priv = netdev->priv;
int i;
DBGP ( "ifec_free\n" );
diff --git a/src/drivers/net/efi/nii.c b/src/drivers/net/efi/nii.c
index be5bce4b..8dd17e4b 100644
--- a/src/drivers/net/efi/nii.c
+++ b/src/drivers/net/efi/nii.c
@@ -1032,8 +1032,9 @@ static void nii_poll_tx ( struct net_device *netdev, unsigned int stat ) {
if ( stat & PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN )
return;
- /* Sanity check */
- assert ( nii->txbuf != NULL );
+ /* Ignore spurious completions reported by some devices */
+ if ( ! nii->txbuf )
+ return;
/* Complete transmission */
iobuf = nii->txbuf;
@@ -1131,7 +1132,7 @@ static void nii_poll ( struct net_device *netdev ) {
/* Get status */
op = NII_OP ( PXE_OPCODE_GET_STATUS,
( PXE_OPFLAGS_GET_INTERRUPT_STATUS |
- ( nii->txbuf ? PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS : 0)|
+ PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS |
( nii->media ? PXE_OPFLAGS_GET_MEDIA_STATUS : 0 ) ) );
if ( ( stat = nii_issue_db ( nii, op, &db, sizeof ( db ) ) ) < 0 ) {
rc = -EIO_STAT ( stat );
@@ -1141,8 +1142,7 @@ static void nii_poll ( struct net_device *netdev ) {
}
/* Process any TX completions */
- if ( nii->txbuf )
- nii_poll_tx ( netdev, stat );
+ nii_poll_tx ( netdev, stat );
/* Process any RX completions */
nii_poll_rx ( netdev );
diff --git a/src/drivers/net/efi/snpnet.c b/src/drivers/net/efi/snpnet.c
index 69ec6f5e..3b09d491 100644
--- a/src/drivers/net/efi/snpnet.c
+++ b/src/drivers/net/efi/snpnet.c
@@ -97,7 +97,7 @@ static const char * snpnet_mac_text ( EFI_MAC_ADDRESS *mac, size_t len ) {
* @v netdev Network device
*/
static void snpnet_dump_mode ( struct net_device *netdev ) {
- struct snp_nic *snp = netdev_priv ( netdev );
+ struct snp_nic *snp = netdev->priv;
EFI_SIMPLE_NETWORK_MODE *mode = snp->snp->Mode;
size_t mac_len = mode->HwAddressSize;
unsigned int i;
@@ -136,7 +136,7 @@ static void snpnet_dump_mode ( struct net_device *netdev ) {
* @v netdev Network device
*/
static void snpnet_check_link ( struct net_device *netdev ) {
- struct snp_nic *snp = netdev_priv ( netdev );
+ struct snp_nic *snp = netdev->priv;
EFI_SIMPLE_NETWORK_MODE *mode = snp->snp->Mode;
/* Do nothing unless media presence detection is supported */
@@ -160,7 +160,7 @@ static void snpnet_check_link ( struct net_device *netdev ) {
*/
static int snpnet_transmit ( struct net_device *netdev,
struct io_buffer *iobuf ) {
- struct snp_nic *snp = netdev_priv ( netdev );
+ struct snp_nic *snp = netdev->priv;
EFI_STATUS efirc;
int rc;
diff --git a/src/drivers/net/etherfabric.c b/src/drivers/net/etherfabric.c
index e43d4336..b40596be 100644
--- a/src/drivers/net/etherfabric.c
+++ b/src/drivers/net/etherfabric.c
@@ -3725,7 +3725,7 @@ efab_receive ( struct efab_nic *efab, unsigned int id, int len, int drop )
static int
efab_transmit ( struct net_device *netdev, struct io_buffer *iob )
{
- struct efab_nic *efab = netdev_priv ( netdev );
+ struct efab_nic *efab = netdev->priv;
struct efab_tx_queue *tx_queue = &efab->tx_queue;
int fill_level, space;
falcon_tx_desc_t *txd;
@@ -3844,7 +3844,7 @@ falcon_handle_event ( struct efab_nic *efab, falcon_event_t *evt )
static void
efab_poll ( struct net_device *netdev )
{
- struct efab_nic *efab = netdev_priv ( netdev );
+ struct efab_nic *efab = netdev->priv;
struct efab_ev_queue *ev_queue = &efab->ev_queue;
struct efab_rx_queue *rx_queue = &efab->rx_queue;
falcon_event_t *evt;
@@ -3883,7 +3883,7 @@ efab_poll ( struct net_device *netdev )
static void
efab_irq ( struct net_device *netdev, int enable )
{
- struct efab_nic *efab = netdev_priv ( netdev );
+ struct efab_nic *efab = netdev->priv;
struct efab_ev_queue *ev_queue = &efab->ev_queue;
switch ( enable ) {
@@ -4032,7 +4032,7 @@ efab_init_mac ( struct efab_nic *efab )
static void
efab_close ( struct net_device *netdev )
{
- struct efab_nic *efab = netdev_priv ( netdev );
+ struct efab_nic *efab = netdev->priv;
falcon_fini_resources ( efab );
efab_free_resources ( efab );
@@ -4043,7 +4043,7 @@ efab_close ( struct net_device *netdev )
static int
efab_open ( struct net_device *netdev )
{
- struct efab_nic *efab = netdev_priv ( netdev );
+ struct efab_nic *efab = netdev->priv;
struct efab_rx_queue *rx_queue = &efab->rx_queue;
int rc;
@@ -4104,7 +4104,7 @@ static void
efab_remove ( struct pci_device *pci )
{
struct net_device *netdev = pci_get_drvdata ( pci );
- struct efab_nic *efab = netdev_priv ( netdev );
+ struct efab_nic *efab = netdev->priv;
if ( efab->membase ) {
falcon_reset ( efab );
@@ -4143,7 +4143,7 @@ efab_probe ( struct pci_device *pci )
pci_set_drvdata ( pci, netdev );
netdev->dev = &pci->dev;
- efab = netdev_priv ( netdev );
+ efab = netdev->priv;
memset ( efab, 0, sizeof ( *efab ) );
efab->netdev = netdev;
diff --git a/src/drivers/net/forcedeth.c b/src/drivers/net/forcedeth.c
index 7fba08a0..ec3a5bdb 100644
--- a/src/drivers/net/forcedeth.c
+++ b/src/drivers/net/forcedeth.c
@@ -677,7 +677,7 @@ set_speed:
static int
forcedeth_open ( struct net_device *netdev )
{
- struct forcedeth_private *priv = netdev_priv ( netdev );
+ struct forcedeth_private *priv = netdev->priv;
void *ioaddr = priv->mmio_addr;
int i;
int rc;
@@ -794,7 +794,7 @@ err_init_rings:
static int
forcedeth_transmit ( struct net_device *netdev, struct io_buffer *iobuf )
{
- struct forcedeth_private *priv = netdev_priv ( netdev );
+ struct forcedeth_private *priv = netdev->priv;
void *ioaddr = priv->mmio_addr;
struct ring_desc *tx_curr_desc;
u32 size = iob_len ( iobuf );
@@ -853,7 +853,7 @@ forcedeth_transmit ( struct net_device *netdev, struct io_buffer *iobuf )
static void
nv_process_tx_packets ( struct net_device *netdev )
{
- struct forcedeth_private *priv = netdev_priv ( netdev );
+ struct forcedeth_private *priv = netdev->priv;
struct ring_desc *tx_curr_desc;
u32 flaglen;
@@ -899,7 +899,7 @@ nv_process_tx_packets ( struct net_device *netdev )
static void
nv_process_rx_packets ( struct net_device *netdev )
{
- struct forcedeth_private *priv = netdev_priv ( netdev );
+ struct forcedeth_private *priv = netdev->priv;
struct io_buffer *curr_iob;
struct ring_desc *rx_curr_desc;
u32 flags, len;
@@ -960,7 +960,7 @@ nv_process_rx_packets ( struct net_device *netdev )
static void
forcedeth_link_status ( struct net_device *netdev )
{
- struct forcedeth_private *priv = netdev_priv ( netdev );
+ struct forcedeth_private *priv = netdev->priv;
void *ioaddr = priv->mmio_addr;
/* Clear the MII link change status by reading the MIIStatus register */
@@ -981,7 +981,7 @@ forcedeth_link_status ( struct net_device *netdev )
static void
forcedeth_poll ( struct net_device *netdev )
{
- struct forcedeth_private *priv = netdev_priv ( netdev );
+ struct forcedeth_private *priv = netdev->priv;
void *ioaddr = priv->mmio_addr;
u32 status;
@@ -1018,7 +1018,7 @@ forcedeth_poll ( struct net_device *netdev )
static void
forcedeth_close ( struct net_device *netdev )
{
- struct forcedeth_private *priv = netdev_priv ( netdev );
+ struct forcedeth_private *priv = netdev->priv;
DBGP ( "forcedeth_close\n" );
@@ -1045,7 +1045,7 @@ forcedeth_close ( struct net_device *netdev )
static void
forcedeth_irq ( struct net_device *netdev, int action )
{
- struct forcedeth_private *priv = netdev_priv ( netdev );
+ struct forcedeth_private *priv = netdev->priv;
DBGP ( "forcedeth_irq\n" );
@@ -1814,7 +1814,7 @@ forcedeth_probe ( struct pci_device *pdev )
netdev->dev = &pdev->dev;
/* Get a reference to our private data */
- priv = netdev_priv ( netdev );
+ priv = netdev->priv;
/* We'll need these set up for the rest of the routines */
priv->pci_dev = pdev;
diff --git a/src/drivers/net/igbvf/igbvf_main.c b/src/drivers/net/igbvf/igbvf_main.c
index a5ed0c45..862ad6a2 100644
--- a/src/drivers/net/igbvf/igbvf_main.c
+++ b/src/drivers/net/igbvf/igbvf_main.c
@@ -179,7 +179,7 @@ static void igbvf_irq_enable ( struct igbvf_adapter *adapter )
**/
static void igbvf_irq ( struct net_device *netdev, int enable )
{
- struct igbvf_adapter *adapter = netdev_priv ( netdev );
+ struct igbvf_adapter *adapter = netdev->priv;
DBG ( "igbvf_irq\n" );
@@ -197,7 +197,7 @@ static void igbvf_irq ( struct net_device *netdev, int enable )
**/
static void igbvf_process_tx_packets ( struct net_device *netdev )
{
- struct igbvf_adapter *adapter = netdev_priv ( netdev );
+ struct igbvf_adapter *adapter = netdev->priv;
uint32_t i;
uint32_t tx_status;
union e1000_adv_tx_desc *tx_curr_desc;
@@ -243,7 +243,7 @@ static void igbvf_process_tx_packets ( struct net_device *netdev )
**/
static void igbvf_process_rx_packets ( struct net_device *netdev )
{
- struct igbvf_adapter *adapter = netdev_priv ( netdev );
+ struct igbvf_adapter *adapter = netdev->priv;
struct e1000_hw *hw = &adapter->hw;
uint32_t i;
uint32_t rx_status;
@@ -306,7 +306,7 @@ static void igbvf_process_rx_packets ( struct net_device *netdev )
*/
static void igbvf_poll ( struct net_device *netdev )
{
- struct igbvf_adapter *adapter = netdev_priv ( netdev );
+ struct igbvf_adapter *adapter = netdev->priv;
uint32_t rx_status;
union e1000_adv_rx_desc *rx_curr_desc;
@@ -612,7 +612,7 @@ int igbvf_setup_rx_resources ( struct igbvf_adapter *adapter )
**/
static int igbvf_open ( struct net_device *netdev )
{
- struct igbvf_adapter *adapter = netdev_priv ( netdev );
+ struct igbvf_adapter *adapter = netdev->priv;
int err;
DBG ("igbvf_open\n");
@@ -667,7 +667,7 @@ err_setup_tx:
**/
static void igbvf_close ( struct net_device *netdev )
{
- struct igbvf_adapter *adapter = netdev_priv ( netdev );
+ struct igbvf_adapter *adapter = netdev->priv;
struct e1000_hw *hw = &adapter->hw;
uint32_t rxdctl;
@@ -698,7 +698,7 @@ static void igbvf_close ( struct net_device *netdev )
*/
static int igbvf_transmit ( struct net_device *netdev, struct io_buffer *iobuf )
{
- struct igbvf_adapter *adapter = netdev_priv ( netdev );
+ struct igbvf_adapter *adapter = netdev->priv;
struct e1000_hw *hw = &adapter->hw;
uint32_t tx_curr = adapter->tx_tail;
union e1000_adv_tx_desc *tx_curr_desc;
@@ -810,7 +810,7 @@ int igbvf_probe ( struct pci_device *pdev )
netdev->dev = &pdev->dev;
/* Initialize driver private storage */
- adapter = netdev_priv ( netdev );
+ adapter = netdev->priv;
memset ( adapter, 0, ( sizeof ( *adapter ) ) );
adapter->pdev = pdev;
@@ -924,7 +924,7 @@ err_alloc_etherdev:
void igbvf_remove ( struct pci_device *pdev )
{
struct net_device *netdev = pci_get_drvdata ( pdev );
- struct igbvf_adapter *adapter = netdev_priv ( netdev );
+ struct igbvf_adapter *adapter = netdev->priv;
DBG ( "igbvf_remove\n" );
diff --git a/src/drivers/net/jme.c b/src/drivers/net/jme.c
index c7307728..298109c2 100644
--- a/src/drivers/net/jme.c
+++ b/src/drivers/net/jme.c
@@ -1153,7 +1153,7 @@ jme_reload_eeprom(struct jme_adapter *jme)
static void
jme_load_macaddr(struct net_device *netdev)
{
- struct jme_adapter *jme = netdev_priv(netdev);
+ struct jme_adapter *jme = netdev->priv;
unsigned char macaddr[6];
u32 val;
diff --git a/src/drivers/net/netfront.c b/src/drivers/net/netfront.c
index 90930a5a..12713c5b 100644
--- a/src/drivers/net/netfront.c
+++ b/src/drivers/net/netfront.c
@@ -1056,9 +1056,11 @@ struct xen_driver netfront_driver __xen_driver = {
* Inhibit emulated PCI devices
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int netfront_net_probe ( struct net_device *netdev ) {
+static int netfront_net_probe ( struct net_device *netdev,
+ void *priv __unused ) {
struct netfront_nic *netfront;
/* Inhibit emulated PCI devices matching an existing netfront device */
diff --git a/src/drivers/net/pcnet32.c b/src/drivers/net/pcnet32.c
index c0dea86a..7da884e5 100644
--- a/src/drivers/net/pcnet32.c
+++ b/src/drivers/net/pcnet32.c
@@ -690,7 +690,7 @@ pcnet32_hw_start ( struct pcnet32_private *priv )
static int
pcnet32_open ( struct net_device *netdev )
{
- struct pcnet32_private *priv = netdev_priv ( netdev );
+ struct pcnet32_private *priv = netdev->priv;
unsigned long ioaddr = priv->pci_dev->ioaddr;
int rc;
u16 val;
@@ -754,7 +754,7 @@ err_setup_tx:
static int
pcnet32_transmit ( struct net_device *netdev, struct io_buffer *iobuf )
{
- struct pcnet32_private *priv = netdev_priv ( netdev );
+ struct pcnet32_private *priv = netdev->priv;
unsigned long ioaddr = priv->pci_dev->ioaddr;
uint32_t tx_len = iob_len ( iobuf );
struct pcnet32_tx_desc *tx_curr_desc;
@@ -802,7 +802,7 @@ pcnet32_transmit ( struct net_device *netdev, struct io_buffer *iobuf )
static void
pcnet32_process_tx_packets ( struct net_device *netdev )
{
- struct pcnet32_private *priv = netdev_priv ( netdev );
+ struct pcnet32_private *priv = netdev->priv;
struct pcnet32_tx_desc *tx_curr_desc;
DBGP ( "pcnet32_process_tx_packets\n" );
@@ -848,7 +848,7 @@ pcnet32_process_tx_packets ( struct net_device *netdev )
static void
pcnet32_process_rx_packets ( struct net_device *netdev )
{
- struct pcnet32_private *priv = netdev_priv ( netdev );
+ struct pcnet32_private *priv = netdev->priv;
struct pcnet32_rx_desc *rx_curr_desc;
u16 status;
u32 len;
@@ -913,7 +913,7 @@ pcnet32_process_rx_packets ( struct net_device *netdev )
static void
pcnet32_poll ( struct net_device *netdev )
{
- struct pcnet32_private *priv = netdev_priv ( netdev );
+ struct pcnet32_private *priv = netdev->priv;
unsigned long ioaddr = priv->pci_dev->ioaddr;
u16 status;
@@ -946,7 +946,7 @@ pcnet32_poll ( struct net_device *netdev )
static void
pcnet32_close ( struct net_device *netdev )
{
- struct pcnet32_private *priv = netdev_priv ( netdev );
+ struct pcnet32_private *priv = netdev->priv;
unsigned long ioaddr = priv->pci_dev->ioaddr;
DBGP ( "pcnet32_close\n" );
@@ -1003,7 +1003,7 @@ static void pcnet32_irq_disable ( struct pcnet32_private *priv )
static void
pcnet32_irq ( struct net_device *netdev, int action )
{
- struct pcnet32_private *priv = netdev_priv ( netdev );
+ struct pcnet32_private *priv = netdev->priv;
DBGP ( "pcnet32_irq\n" );
@@ -1061,7 +1061,7 @@ pcnet32_probe ( struct pci_device *pdev )
netdev->dev = &pdev->dev;
/* Get a reference to our private data */
- priv = netdev_priv ( netdev );
+ priv = netdev->priv;
/* We'll need these set up for the rest of the routines */
priv->pci_dev = pdev;
diff --git a/src/drivers/net/phantom/phantom.c b/src/drivers/net/phantom/phantom.c
index 84345905..e5fd1f31 100644
--- a/src/drivers/net/phantom/phantom.c
+++ b/src/drivers/net/phantom/phantom.c
@@ -1062,7 +1062,7 @@ static inline int phantom_del_macaddr ( struct phantom_nic *phantom,
* @v netdev Network device
*/
static void phantom_poll_link_state ( struct net_device *netdev ) {
- struct phantom_nic *phantom = netdev_priv ( netdev );
+ struct phantom_nic *phantom = netdev->priv;
uint32_t xg_state_p3;
unsigned int link;
@@ -1109,7 +1109,7 @@ static void phantom_poll_link_state ( struct net_device *netdev ) {
* @v netdev Net device
*/
static void phantom_refill_rx_ring ( struct net_device *netdev ) {
- struct phantom_nic *phantom = netdev_priv ( netdev );
+ struct phantom_nic *phantom = netdev->priv;
struct io_buffer *iobuf;
struct phantom_rds rds;
unsigned int handle;
@@ -1160,7 +1160,7 @@ static void phantom_refill_rx_ring ( struct net_device *netdev ) {
* @ret rc Return status code
*/
static int phantom_open ( struct net_device *netdev ) {
- struct phantom_nic *phantom = netdev_priv ( netdev );
+ struct phantom_nic *phantom = netdev->priv;
int rc;
/* Allocate and zero descriptor rings */
@@ -1220,7 +1220,7 @@ static int phantom_open ( struct net_device *netdev ) {
* @v netdev Net device
*/
static void phantom_close ( struct net_device *netdev ) {
- struct phantom_nic *phantom = netdev_priv ( netdev );
+ struct phantom_nic *phantom = netdev->priv;
struct io_buffer *iobuf;
unsigned int i;
@@ -1258,7 +1258,7 @@ static void phantom_close ( struct net_device *netdev ) {
*/
static int phantom_transmit ( struct net_device *netdev,
struct io_buffer *iobuf ) {
- struct phantom_nic *phantom = netdev_priv ( netdev );
+ struct phantom_nic *phantom = netdev->priv;
union phantom_cds cds;
int index;
@@ -1297,7 +1297,7 @@ static int phantom_transmit ( struct net_device *netdev,
* @v netdev Network device
*/
static void phantom_poll ( struct net_device *netdev ) {
- struct phantom_nic *phantom = netdev_priv ( netdev );
+ struct phantom_nic *phantom = netdev->priv;
struct io_buffer *iobuf;
unsigned int irq_vector;
unsigned int irq_state;
@@ -1434,7 +1434,7 @@ static void phantom_poll ( struct net_device *netdev ) {
* @v enable Interrupts should be enabled
*/
static void phantom_irq ( struct net_device *netdev, int enable ) {
- struct phantom_nic *phantom = netdev_priv ( netdev );
+ struct phantom_nic *phantom = netdev->priv;
phantom_writel ( phantom, ( enable ? 1 : 0 ),
phantom->sds_irq_mask_crb );
@@ -2070,7 +2070,7 @@ static int phantom_probe ( struct pci_device *pci ) {
goto err_alloc_etherdev;
}
netdev_init ( netdev, &phantom_operations );
- phantom = netdev_priv ( netdev );
+ phantom = netdev->priv;
pci_set_drvdata ( pci, netdev );
netdev->dev = &pci->dev;
memset ( phantom, 0, sizeof ( *phantom ) );
@@ -2161,7 +2161,7 @@ static int phantom_probe ( struct pci_device *pci ) {
*/
static void phantom_remove ( struct pci_device *pci ) {
struct net_device *netdev = pci_get_drvdata ( pci );
- struct phantom_nic *phantom = netdev_priv ( netdev );
+ struct phantom_nic *phantom = netdev->priv;
unregister_settings ( &phantom->settings );
unregister_netdev ( netdev );
diff --git a/src/drivers/net/sfc/efx_common.c b/src/drivers/net/sfc/efx_common.c
index ad572b1d..2b7a88a5 100644
--- a/src/drivers/net/sfc/efx_common.c
+++ b/src/drivers/net/sfc/efx_common.c
@@ -70,7 +70,7 @@ efx_readl(struct efx_nic *efx, efx_dword_t *value, unsigned int reg)
******************************************************************************/
void efx_probe(struct net_device *netdev, enum efx_revision revision)
{
- struct efx_nic *efx = netdev_priv(netdev);
+ struct efx_nic *efx = netdev->priv;
struct pci_device *pci = container_of(netdev->dev,
struct pci_device, dev);
unsigned int reg = PCI_BASE_ADDRESS_0;
@@ -97,7 +97,7 @@ void efx_probe(struct net_device *netdev, enum efx_revision revision)
void efx_remove(struct net_device *netdev)
{
- struct efx_nic *efx = netdev_priv(netdev);
+ struct efx_nic *efx = netdev->priv;
iounmap(efx->membase);
efx->membase = NULL;
diff --git a/src/drivers/net/sfc/efx_hunt.c b/src/drivers/net/sfc/efx_hunt.c
index 0bce3e45..abe3e832 100644
--- a/src/drivers/net/sfc/efx_hunt.c
+++ b/src/drivers/net/sfc/efx_hunt.c
@@ -100,7 +100,7 @@ efx_hunt_notify_tx_desc(struct efx_nic *efx)
int
efx_hunt_transmit(struct net_device *netdev, struct io_buffer *iob)
{
- struct efx_nic *efx = netdev_priv(netdev);
+ struct efx_nic *efx = netdev->priv;
struct efx_tx_queue *txq = &efx->txq;
int fill_level, space;
efx_tx_desc_t *txd;
@@ -155,7 +155,7 @@ efx_hunt_transmit_done(struct efx_nic *efx, int id)
int efx_hunt_tx_init(struct net_device *netdev, dma_addr_t *dma_addr)
{
- struct efx_nic *efx = netdev_priv(netdev);
+ struct efx_nic *efx = netdev->priv;
struct efx_tx_queue *txq = &efx->txq;
size_t bytes;
@@ -270,7 +270,7 @@ efx_hunt_receive(struct efx_nic *efx, unsigned int id, int len, int drop)
int efx_hunt_rx_init(struct net_device *netdev, dma_addr_t *dma_addr)
{
- struct efx_nic *efx = netdev_priv(netdev);
+ struct efx_nic *efx = netdev->priv;
struct efx_rx_queue *rxq = &efx->rxq;
size_t bytes;
@@ -294,7 +294,7 @@ int efx_hunt_rx_init(struct net_device *netdev, dma_addr_t *dma_addr)
******************************************************************************/
int efx_hunt_ev_init(struct net_device *netdev, dma_addr_t *dma_addr)
{
- struct efx_nic *efx = netdev_priv(netdev);
+ struct efx_nic *efx = netdev->priv;
struct efx_ev_queue *evq = &efx->evq;
size_t bytes;
@@ -404,7 +404,7 @@ efx_hunt_handle_event(struct efx_nic *efx, efx_event_t *evt)
void efx_hunt_poll(struct net_device *netdev)
{
- struct efx_nic *efx = netdev_priv(netdev);
+ struct efx_nic *efx = netdev->priv;
struct efx_ev_queue *evq = &efx->evq;
efx_event_t *evt;
int budget = 10;
@@ -443,7 +443,7 @@ void efx_hunt_poll(struct net_device *netdev)
void efx_hunt_irq(struct net_device *netdev, int enable)
{
- struct efx_nic *efx = netdev_priv(netdev);
+ struct efx_nic *efx = netdev->priv;
efx->int_en = enable;
@@ -465,7 +465,7 @@ void efx_hunt_irq(struct net_device *netdev, int enable)
******************************************************************************/
int efx_hunt_open(struct net_device *netdev)
{
- struct efx_nic *efx = netdev_priv(netdev);
+ struct efx_nic *efx = netdev->priv;
efx_dword_t cmd;
/* Set interrupt moderation to 0*/
@@ -486,7 +486,7 @@ int efx_hunt_open(struct net_device *netdev)
void efx_hunt_close(struct net_device *netdev)
{
- struct efx_nic *efx = netdev_priv(netdev);
+ struct efx_nic *efx = netdev->priv;
struct efx_rx_queue *rxq = &efx->rxq;
struct efx_tx_queue *txq = &efx->txq;
int i;
diff --git a/src/drivers/net/sfc/sfc_hunt.c b/src/drivers/net/sfc/sfc_hunt.c
index a37670ae..43ac229a 100644
--- a/src/drivers/net/sfc/sfc_hunt.c
+++ b/src/drivers/net/sfc/sfc_hunt.c
@@ -1043,7 +1043,7 @@ static void hunt_ev_fini(struct hunt_nic *hunt)
static void
hunt_poll(struct net_device *netdev)
{
- struct hunt_nic *hunt = netdev_priv(netdev);
+ struct hunt_nic *hunt = netdev->priv;
/* If called while already polling, return immediately */
if (hunt->efx.state & EFX_STATE_POLLING)
@@ -1071,7 +1071,7 @@ hunt_poll(struct net_device *netdev)
******************************************************************************/
static int hunt_open(struct net_device *netdev)
{
- struct hunt_nic *hunt = netdev_priv(netdev);
+ struct hunt_nic *hunt = netdev->priv;
int rc;
/* Allocate VIs */
@@ -1133,7 +1133,7 @@ fail2:
static void hunt_close(struct net_device *netdev)
{
- struct hunt_nic *hunt = netdev_priv(netdev);
+ struct hunt_nic *hunt = netdev->priv;
/* Stop datapath */
efx_hunt_close(netdev);
@@ -1187,7 +1187,7 @@ hunt_probe(struct pci_device *pci)
netdev->dev = &pci->dev;
netdev->state |= NETDEV_IRQ_UNSUPPORTED;
- hunt = netdev_priv(netdev);
+ hunt = netdev->priv;
memset(hunt, 0, sizeof(*hunt));
efx = &hunt->efx;
@@ -1290,7 +1290,7 @@ fail1:
static void hunt_remove(struct pci_device *pci)
{
struct net_device *netdev = pci_get_drvdata(pci);
- struct hunt_nic *hunt = netdev_priv(netdev);
+ struct hunt_nic *hunt = netdev->priv;
if (!(hunt->flags &
(1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_NO_ACTIVE_PORT))) {
diff --git a/src/drivers/net/sis190.c b/src/drivers/net/sis190.c
index 0e4f0762..034cac9e 100644
--- a/src/drivers/net/sis190.c
+++ b/src/drivers/net/sis190.c
@@ -107,14 +107,14 @@ static int mdio_read(void *ioaddr, int phy_id, int reg)
static void __mdio_write(struct net_device *dev, int phy_id, int reg, int val)
{
- struct sis190_private *tp = netdev_priv(dev);
+ struct sis190_private *tp = dev->priv;
mdio_write(tp->mmio_addr, phy_id, reg, val);
}
static int __mdio_read(struct net_device *dev, int phy_id, int reg)
{
- struct sis190_private *tp = netdev_priv(dev);
+ struct sis190_private *tp = dev->priv;
return mdio_read(tp->mmio_addr, phy_id, reg);
}
@@ -343,7 +343,7 @@ static void sis190_process_tx(struct sis190_private *tp)
*/
static void sis190_poll(struct net_device *dev)
{
- struct sis190_private *tp = netdev_priv(dev);
+ struct sis190_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
u32 status;
@@ -374,7 +374,7 @@ static inline void sis190_init_ring_indexes(struct sis190_private *tp)
static int sis190_init_ring(struct net_device *dev)
{
- struct sis190_private *tp = netdev_priv(dev);
+ struct sis190_private *tp = dev->priv;
sis190_init_ring_indexes(tp);
@@ -395,7 +395,7 @@ err:
static void sis190_set_rx_mode(struct net_device *dev)
{
- struct sis190_private *tp = netdev_priv(dev);
+ struct sis190_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
u32 mc_filter[2]; /* Multicast hash filter */
u16 rx_mode;
@@ -419,7 +419,7 @@ static void sis190_soft_reset(void *ioaddr)
static void sis190_hw_start(struct net_device *dev)
{
- struct sis190_private *tp = netdev_priv(dev);
+ struct sis190_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
sis190_soft_reset(ioaddr);
@@ -548,7 +548,7 @@ static void sis190_phy_task(struct sis190_private *tp)
static int sis190_open(struct net_device *dev)
{
- struct sis190_private *tp = netdev_priv(dev);
+ struct sis190_private *tp = dev->priv;
int rc;
/* Allocate TX ring */
@@ -587,7 +587,7 @@ error:
static void sis190_down(struct net_device *dev)
{
- struct sis190_private *tp = netdev_priv(dev);
+ struct sis190_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
do {
@@ -597,7 +597,7 @@ static void sis190_down(struct net_device *dev)
static void sis190_free(struct net_device *dev)
{
- struct sis190_private *tp = netdev_priv(dev);
+ struct sis190_private *tp = dev->priv;
int i;
free_phys(tp->TxDescRing, TX_RING_BYTES);
@@ -630,7 +630,7 @@ static void sis190_close(struct net_device *dev)
static int sis190_transmit(struct net_device *dev, struct io_buffer *iob)
{
- struct sis190_private *tp = netdev_priv(dev);
+ struct sis190_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
u32 len, entry;
struct TxDesc *desc;
@@ -804,7 +804,7 @@ static void sis190_mii_probe_88e1111_fixup(struct sis190_private *tp)
*/
static int sis190_mii_probe(struct net_device *dev)
{
- struct sis190_private *tp = netdev_priv(dev);
+ struct sis190_private *tp = dev->priv;
struct mii_if_info *mii_if = &tp->mii_if;
void *ioaddr = tp->mmio_addr;
int phy_id;
@@ -858,7 +858,7 @@ out:
static void sis190_mii_remove(struct net_device *dev)
{
- struct sis190_private *tp = netdev_priv(dev);
+ struct sis190_private *tp = dev->priv;
sis190_free_phy(&tp->first_phy);
}
@@ -879,7 +879,7 @@ static int sis190_init_board(struct pci_device *pdev, struct net_device **netdev
dev->dev = &pdev->dev;
- tp = netdev_priv(dev);
+ tp = dev->priv;
memset(tp, 0, sizeof(*tp));
tp->dev = dev;
@@ -916,7 +916,7 @@ static void sis190_set_rgmii(struct sis190_private *tp, u8 reg)
static int sis190_get_mac_addr_from_eeprom(struct pci_device *pdev __unused,
struct net_device *dev)
{
- struct sis190_private *tp = netdev_priv(dev);
+ struct sis190_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
u16 sig;
int i;
@@ -955,7 +955,7 @@ static int sis190_get_mac_addr_from_eeprom(struct pci_device *pdev __unused,
static int sis190_get_mac_addr_from_apc(struct pci_device *pdev,
struct net_device *dev)
{
- struct sis190_private *tp = netdev_priv(dev);
+ struct sis190_private *tp = dev->priv;
struct pci_device *isa_bridge = NULL;
struct device *d;
u8 reg, tmp8;
@@ -1018,7 +1018,7 @@ static int sis190_get_mac_addr_from_apc(struct pci_device *pdev,
*/
static inline void sis190_init_rxfilter(struct net_device *dev)
{
- struct sis190_private *tp = netdev_priv(dev);
+ struct sis190_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
u16 ctl;
int i;
@@ -1057,7 +1057,7 @@ static int sis190_get_mac_addr(struct pci_device *pdev,
static void sis190_set_speed_auto(struct net_device *dev)
{
- struct sis190_private *tp = netdev_priv(dev);
+ struct sis190_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
int phy_id = tp->mii_if.phy_id;
int val;
@@ -1082,7 +1082,7 @@ static void sis190_set_speed_auto(struct net_device *dev)
static void sis190_irq(struct net_device *dev, int enable)
{
- struct sis190_private *tp = netdev_priv(dev);
+ struct sis190_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
SIS_W32(IntrStatus, 0xffffffff);
@@ -1116,7 +1116,7 @@ static int sis190_probe(struct pci_device *pdev)
pci_set_drvdata(pdev, dev);
- tp = netdev_priv(dev);
+ tp = dev->priv;
rc = sis190_get_mac_addr(pdev, dev);
if (rc < 0)
diff --git a/src/drivers/net/skge.c b/src/drivers/net/skge.c
index 5aa5e2a6..cc7f0b91 100755
--- a/src/drivers/net/skge.c
+++ b/src/drivers/net/skge.c
@@ -213,7 +213,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
*
* static int skge_get_eeprom_len(struct net_device *dev)
* {
- * struct skge_port *skge = netdev_priv(dev);
+ * struct skge_port *skge = dev->priv;
* u32 reg2;
*
* pci_read_config_dword(skge->hw->pdev, PCI_DEV_REG2, &reg2);
@@ -248,7 +248,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
* static int skge_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
* u8 *data)
* {
- * struct skge_port *skge = netdev_priv(dev);
+ * struct skge_port *skge = dev->priv;
* struct pci_dev *pdev = skge->hw->pdev;
* int cap = pci_find_capability(pdev, PCI_CAP_ID_VPD);
* int length = eeprom->len;
@@ -274,7 +274,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
* static int skge_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
* u8 *data)
* {
- * struct skge_port *skge = netdev_priv(dev);
+ * struct skge_port *skge = dev->priv;
* struct pci_dev *pdev = skge->hw->pdev;
* int cap = pci_find_capability(pdev, PCI_CAP_ID_VPD);
* int length = eeprom->len;
@@ -415,7 +415,7 @@ static void skge_link_down(struct skge_port *skge)
static void xm_link_down(struct skge_hw *hw, int port)
{
struct net_device *dev = hw->dev[port];
- struct skge_port *skge = netdev_priv(dev);
+ struct skge_port *skge = dev->priv;
xm_write16(hw, port, XM_IMSK, XM_IMSK_DISABLE);
@@ -553,7 +553,7 @@ static const u16 fiber_pause_map[] = {
static void bcom_check_link(struct skge_hw *hw, int port)
{
struct net_device *dev = hw->dev[port];
- struct skge_port *skge = netdev_priv(dev);
+ struct skge_port *skge = dev->priv;
u16 status;
/* read twice because of latch */
@@ -751,7 +751,7 @@ static void xm_phy_init(struct skge_port *skge)
static int xm_check_link(struct net_device *dev)
{
- struct skge_port *skge = netdev_priv(dev);
+ struct skge_port *skge = dev->priv;
struct skge_hw *hw = skge->hw;
int port = skge->port;
u16 status;
@@ -852,7 +852,7 @@ static void xm_link_timer(struct skge_port *skge)
static void genesis_mac_init(struct skge_hw *hw, int port)
{
struct net_device *dev = hw->dev[port];
- struct skge_port *skge = netdev_priv(dev);
+ struct skge_port *skge = dev->priv;
int i;
u32 r;
const u8 zero[6] = { 0 };
@@ -1209,7 +1209,7 @@ static u16 gm_phy_read(struct skge_hw *hw, int port, u16 reg)
/* Marvell Phy Initialization */
static void yukon_init(struct skge_hw *hw, int port)
{
- struct skge_port *skge = netdev_priv(hw->dev[port]);
+ struct skge_port *skge = hw->dev[port]->priv;
u16 ctrl, ct1000, adv;
if (skge->autoneg == AUTONEG_ENABLE) {
@@ -1325,7 +1325,7 @@ static int is_yukon_lite_a0(struct skge_hw *hw)
static void yukon_mac_init(struct skge_hw *hw, int port)
{
- struct skge_port *skge = netdev_priv(hw->dev[port]);
+ struct skge_port *skge = hw->dev[port]->priv;
int i;
u32 reg;
const u8 *addr = hw->dev[port]->ll_addr;
@@ -1691,7 +1691,7 @@ static void skge_qset(struct skge_port *skge, u16 q,
void skge_free(struct net_device *dev)
{
- struct skge_port *skge = netdev_priv(dev);
+ struct skge_port *skge = dev->priv;
free(skge->rx_ring.start);
skge->rx_ring.start = NULL;
@@ -1706,7 +1706,7 @@ void skge_free(struct net_device *dev)
static int skge_up(struct net_device *dev)
{
- struct skge_port *skge = netdev_priv(dev);
+ struct skge_port *skge = dev->priv;
struct skge_hw *hw = skge->hw;
int port = skge->port;
u32 chunk, ram_addr;
@@ -1789,7 +1789,7 @@ static void skge_rx_stop(struct skge_hw *hw, int port)
static void skge_down(struct net_device *dev)
{
- struct skge_port *skge = netdev_priv(dev);
+ struct skge_port *skge = dev->priv;
struct skge_hw *hw = skge->hw;
int port = skge->port;
@@ -1862,7 +1862,7 @@ static inline int skge_tx_avail(const struct skge_ring *ring)
static int skge_xmit_frame(struct net_device *dev, struct io_buffer *iob)
{
- struct skge_port *skge = netdev_priv(dev);
+ struct skge_port *skge = dev->priv;
struct skge_hw *hw = skge->hw;
struct skge_element *e;
struct skge_tx_desc *td;
@@ -1908,7 +1908,7 @@ static int skge_xmit_frame(struct net_device *dev, struct io_buffer *iob)
/* Free all buffers in transmit ring */
static void skge_tx_clean(struct net_device *dev)
{
- struct skge_port *skge = netdev_priv(dev);
+ struct skge_port *skge = dev->priv;
struct skge_element *e;
for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) {
@@ -1939,7 +1939,7 @@ static inline int bad_phy_status(const struct skge_hw *hw, u32 status)
/* Free all buffers in Tx ring which are no longer owned by device */
static void skge_tx_done(struct net_device *dev)
{
- struct skge_port *skge = netdev_priv(dev);
+ struct skge_port *skge = dev->priv;
struct skge_ring *ring = &skge->tx_ring;
struct skge_element *e;
@@ -1961,7 +1961,7 @@ static void skge_tx_done(struct net_device *dev)
static void skge_rx_refill(struct net_device *dev)
{
- struct skge_port *skge = netdev_priv(dev);
+ struct skge_port *skge = dev->priv;
struct skge_ring *ring = &skge->rx_ring;
struct skge_element *e;
struct io_buffer *iob;
@@ -2003,7 +2003,7 @@ static void skge_rx_refill(struct net_device *dev)
static void skge_rx_done(struct net_device *dev)
{
- struct skge_port *skge = netdev_priv(dev);
+ struct skge_port *skge = dev->priv;
struct skge_ring *ring = &skge->rx_ring;
struct skge_rx_desc *rd;
struct skge_element *e;
@@ -2050,7 +2050,7 @@ static void skge_rx_done(struct net_device *dev)
static void skge_poll(struct net_device *dev)
{
- struct skge_port *skge = netdev_priv(dev);
+ struct skge_port *skge = dev->priv;
struct skge_hw *hw = skge->hw;
u32 status;
@@ -2085,7 +2085,7 @@ static void skge_phyirq(struct skge_hw *hw)
for (port = 0; port < hw->ports; port++) {
struct net_device *dev = hw->dev[port];
- struct skge_port *skge = netdev_priv(dev);
+ struct skge_port *skge = dev->priv;
if (hw->chip_id != CHIP_ID_GENESIS)
yukon_phy_intr(skge);
@@ -2302,7 +2302,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
dev->dev = &hw->pdev->dev;
- skge = netdev_priv(dev);
+ skge = dev->priv;
skge->netdev = dev;
skge->hw = hw;
@@ -2446,7 +2446,7 @@ static void skge_remove(struct pci_device *pdev)
* This is a iPXE Network Driver API function.
*/
static void skge_net_irq ( struct net_device *dev, int enable ) {
- struct skge_port *skge = netdev_priv(dev);
+ struct skge_port *skge = dev->priv;
struct skge_hw *hw = skge->hw;
if (enable)
diff --git a/src/drivers/net/sky2.c b/src/drivers/net/sky2.c
index 9d612c99..26396585 100644
--- a/src/drivers/net/sky2.c
+++ b/src/drivers/net/sky2.c
@@ -296,7 +296,7 @@ static const u16 gm_fc_disable[] = {
static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
{
- struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
+ struct sky2_port *sky2 = hw->dev[port]->priv;
u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg;
if (sky2->autoneg == AUTONEG_ENABLE &&
@@ -1128,7 +1128,7 @@ static void sky2_free_rings(struct sky2_port *sky2)
/* Bring up network interface. */
static int sky2_up(struct net_device *dev)
{
- struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_port *sky2 = dev->priv;
struct sky2_hw *hw = sky2->hw;
unsigned port = sky2->port;
u32 imask, ramsize;
@@ -1237,7 +1237,7 @@ static inline int tx_avail(const struct sky2_port *sky2)
*/
static int sky2_xmit_frame(struct net_device *dev, struct io_buffer *iob)
{
- struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_port *sky2 = dev->priv;
struct sky2_hw *hw = sky2->hw;
struct sky2_tx_le *le = NULL;
struct tx_ring_info *re;
@@ -1303,7 +1303,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
/* Cleanup all untransmitted buffers, assume transmitter not running */
static void sky2_tx_clean(struct net_device *dev)
{
- struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_port *sky2 = dev->priv;
sky2_tx_complete(sky2, sky2->tx_prod);
}
@@ -1311,7 +1311,7 @@ static void sky2_tx_clean(struct net_device *dev)
/* Network shutdown */
static void sky2_down(struct net_device *dev)
{
- struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_port *sky2 = dev->priv;
struct sky2_hw *hw = sky2->hw;
unsigned port = sky2->port;
u16 ctrl;
@@ -1511,7 +1511,7 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux)
static void sky2_phy_intr(struct sky2_hw *hw, unsigned port)
{
struct net_device *dev = hw->dev[port];
- struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_port *sky2 = dev->priv;
u16 istatus, phystat;
istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT);
@@ -1570,7 +1570,7 @@ static struct io_buffer *receive_new(struct sky2_port *sky2,
static struct io_buffer *sky2_receive(struct net_device *dev,
u16 length, u32 status)
{
- struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_port *sky2 = dev->priv;
struct rx_ring_info *re = sky2->rx_ring + sky2->rx_next;
struct io_buffer *iob = NULL;
u16 count = (status & GMR_FS_LEN) >> 16;
@@ -1634,7 +1634,7 @@ error:
/* Transmit complete */
static inline void sky2_tx_done(struct net_device *dev, u16 last)
{
- struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_port *sky2 = dev->priv;
sky2_tx_complete(sky2, last);
}
@@ -1700,10 +1700,10 @@ static void sky2_status_intr(struct sky2_hw *hw, u16 idx)
sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
if (rx[0])
- sky2_rx_update(netdev_priv(hw->dev[0]), Q_R1);
+ sky2_rx_update(hw->dev[0]->priv, Q_R1);
if (rx[1])
- sky2_rx_update(netdev_priv(hw->dev[1]), Q_R2);
+ sky2_rx_update(hw->dev[1]->priv, Q_R2);
}
static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status)
@@ -1809,7 +1809,7 @@ static void sky2_le_error(struct sky2_hw *hw, unsigned port,
u16 q, unsigned ring_size __unused)
{
struct net_device *dev = hw->dev[port];
- struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_port *sky2 = dev->priv;
int idx;
const u64 *le = (q == Q_R1 || q == Q_R2)
? (u64 *) sky2->rx_le : (u64 *) sky2->tx_le;
@@ -1853,7 +1853,7 @@ static void sky2_err_intr(struct sky2_hw *hw, u32 status)
static void sky2_poll(struct net_device *dev)
{
- struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_port *sky2 = dev->priv;
struct sky2_hw *hw = sky2->hw;
u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
u16 idx;
@@ -2152,7 +2152,7 @@ static u32 sky2_supported_modes(const struct sky2_hw *hw)
static void sky2_set_multicast(struct net_device *dev)
{
- struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_port *sky2 = dev->priv;
struct sky2_hw *hw = sky2->hw;
unsigned port = sky2->port;
u16 reg;
@@ -2189,7 +2189,7 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw,
dev->dev = &hw->pdev->dev;
- sky2 = netdev_priv(dev);
+ sky2 = dev->priv;
sky2->netdev = dev;
sky2->hw = hw;
@@ -2241,7 +2241,7 @@ static const char *sky2_name(u8 chipid, char *buf, int sz)
static void sky2_net_irq(struct net_device *dev, int enable)
{
- struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_port *sky2 = dev->priv;
struct sky2_hw *hw = sky2->hw;
u32 imask = sky2_read32(hw, B0_IMSK);
diff --git a/src/drivers/net/tg3/tg3.c b/src/drivers/net/tg3/tg3.c
index cec599c1..559c2d63 100644
--- a/src/drivers/net/tg3/tg3.c
+++ b/src/drivers/net/tg3/tg3.c
@@ -233,7 +233,7 @@ int tg3_init_rings(struct tg3 *tp)
static int tg3_open(struct net_device *dev)
{ DBGP("%s\n", __func__);
- struct tg3 *tp = netdev_priv(dev);
+ struct tg3 *tp = dev->priv;
struct tg3_rx_prodring_set *tpr = &tp->prodring;
int err = 0;
@@ -299,7 +299,7 @@ static void __unused tw32_mailbox2(struct tg3 *tp, uint32_t reg, uint32_t val)
static int tg3_transmit(struct net_device *dev, struct io_buffer *iob)
{ DBGP("%s\n", __func__);
- struct tg3 *tp = netdev_priv(dev);
+ struct tg3 *tp = dev->priv;
u32 len, entry;
dma_addr_t mapping;
@@ -333,7 +333,7 @@ static int tg3_transmit(struct net_device *dev, struct io_buffer *iob)
static void tg3_tx_complete(struct net_device *dev)
{ DBGP("%s\n", __func__);
- struct tg3 *tp = netdev_priv(dev);
+ struct tg3 *tp = dev->priv;
u32 hw_idx = tp->hw_status->idx[0].tx_consumer;
u32 sw_idx = tp->tx_cons;
@@ -427,7 +427,7 @@ static void tg3_refill_prod_ring(struct tg3 *tp)
static void tg3_rx_complete(struct net_device *dev)
{ DBGP("%s\n", __func__);
- struct tg3 *tp = netdev_priv(dev);
+ struct tg3 *tp = dev->priv;
u32 sw_idx = tp->rx_rcb_ptr;
u16 hw_idx;
@@ -478,7 +478,7 @@ static void tg3_rx_complete(struct net_device *dev)
static void tg3_poll(struct net_device *dev)
{ DBGP("%s\n", __func__);
- struct tg3 *tp = netdev_priv(dev);
+ struct tg3 *tp = dev->priv;
/* ACK interrupts */
/*
@@ -496,7 +496,7 @@ static void tg3_poll(struct net_device *dev)
static void tg3_close(struct net_device *dev)
{ DBGP("%s\n", __func__);
- struct tg3 *tp = netdev_priv(dev);
+ struct tg3 *tp = dev->priv;
DBGP("%s\n", __func__);
@@ -511,7 +511,7 @@ static void tg3_close(struct net_device *dev)
static void tg3_irq(struct net_device *dev, int enable)
{ DBGP("%s\n", __func__);
- struct tg3 *tp = netdev_priv(dev);
+ struct tg3 *tp = dev->priv;
DBGP("%s: %d\n", __func__, enable);
@@ -735,7 +735,7 @@ static int tg3_init_one(struct pci_device *pdev)
dev->dev = &pdev->dev;
- tp = netdev_priv(dev);
+ tp = dev->priv;
tp->pdev = pdev;
tp->dev = dev;
tp->rx_mode = TG3_DEF_RX_MODE;
diff --git a/src/drivers/net/tg3/tg3_hw.c b/src/drivers/net/tg3/tg3_hw.c
index 798f8519..9a70413b 100644
--- a/src/drivers/net/tg3/tg3_hw.c
+++ b/src/drivers/net/tg3/tg3_hw.c
@@ -1717,7 +1717,7 @@ int tg3_get_device_address(struct tg3 *tp)
static void __tg3_set_rx_mode(struct net_device *dev)
{ DBGP("%s\n", __func__);
- struct tg3 *tp = netdev_priv(dev);
+ struct tg3 *tp = dev->priv;
u32 rx_mode;
rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC |
diff --git a/src/drivers/net/vmxnet3.c b/src/drivers/net/vmxnet3.c
index 63bcf0e0..3800d6b7 100644
--- a/src/drivers/net/vmxnet3.c
+++ b/src/drivers/net/vmxnet3.c
@@ -90,7 +90,7 @@ static inline uint32_t vmxnet3_command ( struct vmxnet3_nic *vmxnet,
*/
static int vmxnet3_transmit ( struct net_device *netdev,
struct io_buffer *iobuf ) {
- struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ struct vmxnet3_nic *vmxnet = netdev->priv;
struct vmxnet3_tx_desc *tx_desc;
unsigned int fill;
unsigned int desc_idx;
@@ -139,7 +139,7 @@ static int vmxnet3_transmit ( struct net_device *netdev,
* @v netdev Network device
*/
static void vmxnet3_poll_tx ( struct net_device *netdev ) {
- struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ struct vmxnet3_nic *vmxnet = netdev->priv;
struct vmxnet3_tx_comp *tx_comp;
struct io_buffer *iobuf;
unsigned int comp_idx;
@@ -188,7 +188,7 @@ static void vmxnet3_poll_tx ( struct net_device *netdev ) {
* @v netdev Network device
*/
static void vmxnet3_flush_tx ( struct net_device *netdev ) {
- struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ struct vmxnet3_nic *vmxnet = netdev->priv;
unsigned int i;
for ( i = 0 ; i < VMXNET3_NUM_TX_DESC ; i++ ) {
@@ -206,7 +206,7 @@ static void vmxnet3_flush_tx ( struct net_device *netdev ) {
* @v netdev Network device
*/
static void vmxnet3_refill_rx ( struct net_device *netdev ) {
- struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ struct vmxnet3_nic *vmxnet = netdev->priv;
struct vmxnet3_rx_desc *rx_desc;
struct io_buffer *iobuf;
unsigned int orig_rx_prod = vmxnet->count.rx_prod;
@@ -261,7 +261,7 @@ static void vmxnet3_refill_rx ( struct net_device *netdev ) {
* @v netdev Network device
*/
static void vmxnet3_poll_rx ( struct net_device *netdev ) {
- struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ struct vmxnet3_nic *vmxnet = netdev->priv;
struct vmxnet3_rx_comp *rx_comp;
struct io_buffer *iobuf;
unsigned int comp_idx;
@@ -315,7 +315,7 @@ static void vmxnet3_poll_rx ( struct net_device *netdev ) {
* @v netdev Network device
*/
static void vmxnet3_flush_rx ( struct net_device *netdev ) {
- struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ struct vmxnet3_nic *vmxnet = netdev->priv;
struct io_buffer *iobuf;
unsigned int i;
@@ -333,7 +333,7 @@ static void vmxnet3_flush_rx ( struct net_device *netdev ) {
* @v netdev Network device
*/
static void vmxnet3_check_link ( struct net_device *netdev ) {
- struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ struct vmxnet3_nic *vmxnet = netdev->priv;
uint32_t state;
int link_up;
unsigned int link_speed;
@@ -360,7 +360,7 @@ static void vmxnet3_check_link ( struct net_device *netdev ) {
* @v netdev Network device
*/
static void vmxnet3_poll_events ( struct net_device *netdev ) {
- struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ struct vmxnet3_nic *vmxnet = netdev->priv;
uint32_t events;
/* Do nothing unless there are events to process */
@@ -424,7 +424,7 @@ static void vmxnet3_poll ( struct net_device *netdev ) {
* @v enable Interrupts should be enabled
*/
static void vmxnet3_irq ( struct net_device *netdev, int enable ) {
- struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ struct vmxnet3_nic *vmxnet = netdev->priv;
DBGC ( vmxnet, "VMXNET3 %p %s IRQ not implemented\n",
vmxnet, ( enable ? "enable" : "disable" ) );
@@ -456,7 +456,7 @@ static void vmxnet3_set_ll_addr ( struct vmxnet3_nic *vmxnet,
* @ret rc Return status code
*/
static int vmxnet3_open ( struct net_device *netdev ) {
- struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ struct vmxnet3_nic *vmxnet = netdev->priv;
struct vmxnet3_shared *shared;
struct vmxnet3_queues *queues;
uint64_t shared_bus;
@@ -554,7 +554,7 @@ static int vmxnet3_open ( struct net_device *netdev ) {
* @v netdev Network device
*/
static void vmxnet3_close ( struct net_device *netdev ) {
- struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ struct vmxnet3_nic *vmxnet = netdev->priv;
vmxnet3_command ( vmxnet, VMXNET3_CMD_QUIESCE_DEV );
vmxnet3_command ( vmxnet, VMXNET3_CMD_RESET_DEV );
@@ -633,7 +633,7 @@ static int vmxnet3_probe ( struct pci_device *pci ) {
goto err_alloc_etherdev;
}
netdev_init ( netdev, &vmxnet3_operations );
- vmxnet = netdev_priv ( netdev );
+ vmxnet = netdev->priv;
pci_set_drvdata ( pci, netdev );
netdev->dev = &pci->dev;
memset ( vmxnet, 0, sizeof ( *vmxnet ) );
@@ -699,7 +699,7 @@ static int vmxnet3_probe ( struct pci_device *pci ) {
*/
static void vmxnet3_remove ( struct pci_device *pci ) {
struct net_device *netdev = pci_get_drvdata ( pci );
- struct vmxnet3_nic *vmxnet = netdev_priv ( netdev );
+ struct vmxnet3_nic *vmxnet = netdev->priv;
unregister_netdev ( netdev );
iounmap ( vmxnet->vd );
diff --git a/src/drivers/net/vxge/vxge_main.c b/src/drivers/net/vxge/vxge_main.c
index 63192831..e323701f 100644
--- a/src/drivers/net/vxge/vxge_main.c
+++ b/src/drivers/net/vxge/vxge_main.c
@@ -186,7 +186,7 @@ vxge_xmit(struct net_device *dev, struct io_buffer *iobuf)
vxge_trace();
- vdev = (struct vxgedev *)netdev_priv(dev);
+ vdev = (struct vxgedev *)dev->priv;
if (!is_vxge_card_up(vdev)) {
vxge_debug(VXGE_ERR,
@@ -235,7 +235,7 @@ static void vxge_poll(struct net_device *ndev)
vxge_debug(VXGE_POLL, "%s:%d \n", __func__, __LINE__);
- vdev = (struct vxgedev *)netdev_priv(ndev);
+ vdev = (struct vxgedev *)ndev->priv;
hldev = (struct __vxge_hw_device *)pci_get_drvdata(vdev->pdev);
if (!is_vxge_card_up(vdev))
@@ -263,7 +263,7 @@ static void vxge_irq(struct net_device *netdev __unused, int action)
vxge_debug(VXGE_INFO,
"%s:%d action(%d)\n", __func__, __LINE__, action);
- vdev = (struct vxgedev *)netdev_priv(netdev);
+ vdev = (struct vxgedev *)netdev->priv;
hldev = (struct __vxge_hw_device *)pci_get_drvdata(vdev->pdev);
switch (action) {
@@ -297,7 +297,7 @@ vxge_open(struct net_device *dev)
vxge_debug(VXGE_INFO, "%s: %s:%d\n",
VXGE_DRIVER_NAME, __func__, __LINE__);
- vdev = (struct vxgedev *)netdev_priv(dev);
+ vdev = (struct vxgedev *)dev->priv;
hldev = (struct __vxge_hw_device *)pci_get_drvdata(vdev->pdev);
/* make sure you have link off by default every time Nic is
@@ -369,7 +369,7 @@ static void vxge_close(struct net_device *dev)
vxge_debug(VXGE_INFO, "%s: %s:%d\n",
dev->name, __func__, __LINE__);
- vdev = (struct vxgedev *)netdev_priv(dev);
+ vdev = (struct vxgedev *)dev->priv;
hldev = (struct __vxge_hw_device *)pci_get_drvdata(vdev->pdev);
if (!is_vxge_card_up(vdev))
@@ -420,7 +420,7 @@ int vxge_device_register(struct __vxge_hw_device *hldev,
vxge_debug(VXGE_INFO, "%s:%d netdev registering\n",
__func__, __LINE__);
- vdev = netdev_priv(ndev);
+ vdev = ndev->priv;
memset(vdev, 0, sizeof(struct vxgedev));
vdev->ndev = ndev;
@@ -683,7 +683,7 @@ vxge_remove(struct pci_device *pdev)
return;
ndev = hldev->ndev;
- vdev = netdev_priv(ndev);
+ vdev = ndev->priv;
iounmap(vdev->bar0);
diff --git a/src/drivers/usb/usbkbd.c b/src/drivers/usb/usbkbd.c
index b284e584..cf881ad1 100644
--- a/src/drivers/usb/usbkbd.c
+++ b/src/drivers/usb/usbkbd.c
@@ -95,7 +95,7 @@ static unsigned int usbkbd_map ( unsigned int keycode, unsigned int modifiers,
}
} else if ( keycode <= USBKBD_KEY_UP ) {
/* Special keys */
- static const uint16_t special[] = {
+ static const unsigned int special[] = {
0, 0, 0, 0, 0, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9,
KEY_F10, KEY_F11, KEY_F12, 0, 0, 0, KEY_IC, KEY_HOME,
KEY_PPAGE, KEY_DC, KEY_END, KEY_NPAGE, KEY_RIGHT,
@@ -110,7 +110,7 @@ static unsigned int usbkbd_map ( unsigned int keycode, unsigned int modifiers,
if ( leds & USBKBD_LED_NUM_LOCK ) {
key = "1234567890." [ keycode - USBKBD_KEY_PAD_1 ];
} else {
- static const uint16_t keypad[] = {
+ static const unsigned int keypad[] = {
KEY_END, KEY_DOWN, KEY_NPAGE, KEY_LEFT, 0,
KEY_RIGHT, KEY_HOME, KEY_UP, KEY_PPAGE,
KEY_IC, KEY_DC
diff --git a/src/hci/commands/image_cmd.c b/src/hci/commands/image_cmd.c
index 4a7c500a..bf97b4de 100644
--- a/src/hci/commands/image_cmd.c
+++ b/src/hci/commands/image_cmd.c
@@ -129,7 +129,7 @@ static int imgsingle_exec ( int argc, char **argv,
&image ) ) != 0 )
goto err_acquire;
} else {
- image = image_find_selected();
+ image = find_image_tag ( &selected_image );
if ( ! image ) {
printf ( "No image selected\n" );
goto err_acquire;
diff --git a/src/hci/commands/shim_cmd.c b/src/hci/commands/shim_cmd.c
new file mode 100644
index 00000000..11956290
--- /dev/null
+++ b/src/hci/commands/shim_cmd.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2023 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <getopt.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <ipxe/efi/efi_image.h>
+#include <usr/imgmgmt.h>
+#include <usr/shimmgmt.h>
+
+/** @file
+ *
+ * EFI shim command
+ *
+ */
+
+/* Exist as a dummy command on non-EFI platforms */
+#ifdef PLATFORM_efi
+#define shim_dummy 0
+#else
+#define shim_dummy 1
+#endif
+
+/** "shim" options */
+struct shim_options {
+ /** Download timeout */
+ unsigned long timeout;
+ /** Require third party loader */
+ int require_loader;
+ /** Allow PXE base code protocol */
+ int allow_pxe;
+ /** Allow SBAT variable access */
+ int allow_sbat;
+};
+
+/** "shim" option list */
+static struct option_descriptor shim_opts[] = {
+ OPTION_DESC ( "timeout", 't', required_argument,
+ struct shim_options, timeout, parse_timeout ),
+ OPTION_DESC ( "require-loader", 'l', no_argument,
+ struct shim_options, require_loader, parse_flag ),
+ OPTION_DESC ( "allow-pxe", 'p', no_argument,
+ struct shim_options, allow_pxe, parse_flag ),
+ OPTION_DESC ( "allow-sbat", 's', no_argument,
+ struct shim_options, allow_sbat, parse_flag ),
+};
+
+/** "shim" command descriptor */
+static struct command_descriptor shim_cmd =
+ COMMAND_DESC ( struct shim_options, shim_opts, 0, 1, NULL );
+
+/**
+ * The "shim" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int shim_exec ( int argc, char **argv ) {
+ struct shim_options opts;
+ struct image *image = NULL;
+ struct image *kernel;
+ char *name_uri;
+ int download;
+ int rc;
+
+ /* Do absolutely nothing if this is a non-EFI platform */
+ if ( shim_dummy ) {
+ rc = 0;
+ goto err_dummy;
+ }
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &shim_cmd, &opts ) ) != 0 )
+ goto err_parse;
+
+ /* Decide whether or not to download images */
+ kernel = find_image_tag ( &selected_image );
+ download = ( ! ( kernel && efi_can_load ( kernel ) ) );
+
+ /* Parse name/URI string */
+ name_uri = argv[optind];
+
+ /* Acquire image, if applicable */
+ if ( download && name_uri &&
+ ( ( rc = imgacquire ( name_uri, opts.timeout,
+ &image ) ) != 0 ) ) {
+ goto err_image;
+ }
+
+ /* (Un)register as shim */
+ if ( ( rc = shim ( image, opts.require_loader, opts.allow_pxe,
+ opts.allow_sbat ) ) != 0 )
+ goto err_shim;
+
+ err_shim:
+ err_image:
+ err_parse:
+ err_dummy:
+ return rc;
+}
+
+/** Shim commands */
+struct command shim_commands[] __command = {
+ {
+ .name = "shim",
+ .exec = shim_exec,
+ },
+};
diff --git a/src/image/efi_image.c b/src/image/efi_image.c
index 467fb05a..104753a8 100644
--- a/src/image/efi_image.c
+++ b/src/image/efi_image.c
@@ -31,6 +31,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/efi/efi_wrap.h>
#include <ipxe/efi/efi_pxe.h>
#include <ipxe/efi/efi_driver.h>
+#include <ipxe/efi/efi_image.h>
+#include <ipxe/efi/efi_shim.h>
#include <ipxe/image.h>
#include <ipxe/init.h>
#include <ipxe/features.h>
@@ -109,18 +111,14 @@ efi_image_path ( struct image *image, EFI_DEVICE_PATH_PROTOCOL *parent ) {
*/
static wchar_t * efi_image_cmdline ( struct image *image ) {
wchar_t *cmdline;
- size_t len;
- len = ( strlen ( image->name ) +
- ( image->cmdline ?
- ( 1 /* " " */ + strlen ( image->cmdline ) ) : 0 ) );
- cmdline = zalloc ( ( len + 1 /* NUL */ ) * sizeof ( wchar_t ) );
- if ( ! cmdline )
+ /* Allocate and construct command line */
+ if ( efi_asprintf ( &cmdline, "%s%s%s", image->name,
+ ( image->cmdline ? " " : "" ),
+ ( image->cmdline ? image->cmdline : "" ) ) < 0 ) {
return NULL;
- efi_snprintf ( cmdline, ( len + 1 /* NUL */ ), "%s%s%s",
- image->name,
- ( image->cmdline ? " " : "" ),
- ( image->cmdline ? image->cmdline : "" ) );
+ }
+
return cmdline;
}
@@ -138,9 +136,12 @@ static int efi_image_exec ( struct image *image ) {
EFI_LOADED_IMAGE_PROTOCOL *image;
void *interface;
} loaded;
+ struct image *shim;
+ struct image *exec;
EFI_HANDLE handle;
EFI_MEMORY_TYPE type;
wchar_t *cmdline;
+ unsigned int toggle;
EFI_STATUS efirc;
int rc;
@@ -153,6 +154,21 @@ static int efi_image_exec ( struct image *image ) {
goto err_no_snpdev;
}
+ /* Use shim instead of directly executing image if applicable */
+ shim = ( efi_can_load ( image ) ?
+ NULL : find_image_tag ( &efi_shim ) );
+ exec = ( shim ? shim : image );
+ if ( shim ) {
+ DBGC ( image, "EFIIMAGE %s executing via %s\n",
+ image->name, shim->name );
+ }
+
+ /* Re-register as a hidden image to allow for access via file I/O */
+ toggle = ( ~image->flags & IMAGE_HIDDEN );
+ image->flags |= IMAGE_HIDDEN;
+ if ( ( rc = register_image ( image ) ) != 0 )
+ goto err_register_image;
+
/* Install file I/O protocols */
if ( ( rc = efi_file_install ( snpdev->handle ) ) != 0 ) {
DBGC ( image, "EFIIMAGE %s could not install file protocol: "
@@ -175,7 +191,7 @@ static int efi_image_exec ( struct image *image ) {
}
/* Create device path for image */
- path = efi_image_path ( image, snpdev->path );
+ path = efi_image_path ( exec, snpdev->path );
if ( ! path ) {
DBGC ( image, "EFIIMAGE %s could not create device path\n",
image->name );
@@ -192,11 +208,20 @@ static int efi_image_exec ( struct image *image ) {
goto err_cmdline;
}
+ /* Install shim special handling if applicable */
+ if ( shim &&
+ ( ( rc = efi_shim_install ( shim, snpdev->handle,
+ &cmdline ) ) != 0 ) ){
+ DBGC ( image, "EFIIMAGE %s could not install shim handling: "
+ "%s\n", image->name, strerror ( rc ) );
+ goto err_shim_install;
+ }
+
/* Attempt loading image */
handle = NULL;
if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, path,
- user_to_virt ( image->data, 0 ),
- image->len, &handle ) ) != 0 ) {
+ user_to_virt ( exec->data, 0 ),
+ exec->len, &handle ) ) != 0 ) {
/* Not an EFI image */
rc = -EEFI_LOAD ( efirc );
DBGC ( image, "EFIIMAGE %s could not load: %s\n",
@@ -286,6 +311,9 @@ static int efi_image_exec ( struct image *image ) {
if ( rc != 0 )
bs->UnloadImage ( handle );
err_load_image:
+ if ( shim )
+ efi_shim_uninstall();
+ err_shim_install:
free ( cmdline );
err_cmdline:
free ( path );
@@ -296,6 +324,9 @@ static int efi_image_exec ( struct image *image ) {
err_pxe_install:
efi_file_uninstall ( snpdev->handle );
err_file_install:
+ unregister_image ( image );
+ err_register_image:
+ image->flags ^= toggle;
err_no_snpdev:
return rc;
}
@@ -346,9 +377,75 @@ static int efi_image_probe ( struct image *image ) {
return rc;
}
-/** EFI image type */
-struct image_type efi_image_type __image_type ( PROBE_NORMAL ) = {
- .name = "EFI",
- .probe = efi_image_probe,
- .exec = efi_image_exec,
+/**
+ * Probe EFI PE image
+ *
+ * @v image EFI file
+ * @ret rc Return status code
+ *
+ * The extremely broken UEFI Secure Boot model provides no way for us
+ * to unambiguously determine that a valid EFI executable image was
+ * rejected by LoadImage() because it failed signature verification.
+ * We must therefore use heuristics to guess whether not an image that
+ * was rejected by LoadImage() could still be loaded via a separate PE
+ * loader such as the UEFI shim.
+ */
+static int efi_pe_image_probe ( struct image *image ) {
+ const UINT16 magic = ( ( sizeof ( UINTN ) == sizeof ( uint32_t ) ) ?
+ EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC :
+ EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC );
+ union {
+ EFI_IMAGE_DOS_HEADER dos;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION pe;
+ } u;
+
+ /* Check for existence of DOS header */
+ if ( image->len < sizeof ( u.dos ) ) {
+ DBGC ( image, "EFIIMAGE %s too short for DOS header\n",
+ image->name );
+ return -ENOEXEC;
+ }
+ copy_from_user ( &u.dos, image->data, 0, sizeof ( u.dos ) );
+ if ( u.dos.e_magic != EFI_IMAGE_DOS_SIGNATURE ) {
+ DBGC ( image, "EFIIMAGE %s missing MZ signature\n",
+ image->name );
+ return -ENOEXEC;
+ }
+
+ /* Check for existence of PE header */
+ if ( ( image->len < u.dos.e_lfanew ) ||
+ ( ( image->len - u.dos.e_lfanew ) < sizeof ( u.pe ) ) ) {
+ DBGC ( image, "EFIIMAGE %s too short for PE header\n",
+ image->name );
+ return -ENOEXEC;
+ }
+ copy_from_user ( &u.pe, image->data, u.dos.e_lfanew, sizeof ( u.pe ) );
+ if ( u.pe.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE ) {
+ DBGC ( image, "EFIIMAGE %s missing PE signature\n",
+ image->name );
+ return -ENOEXEC;
+ }
+
+ /* Check PE header magic */
+ if ( u.pe.Pe32.OptionalHeader.Magic != magic ) {
+ DBGC ( image, "EFIIMAGE %s incorrect magic %04x\n",
+ image->name, u.pe.Pe32.OptionalHeader.Magic );
+ return -ENOEXEC;
+ }
+
+ return 0;
+}
+
+/** EFI image types */
+struct image_type efi_image_type[] __image_type ( PROBE_NORMAL ) = {
+ {
+ .name = "EFI",
+ .probe = efi_image_probe,
+ .exec = efi_image_exec,
+ },
+ {
+ .name = "EFIPE",
+ .probe = efi_pe_image_probe,
+ .exec = efi_image_exec,
+ },
};
diff --git a/src/image/script.c b/src/image/script.c
index b34df1e2..49b35640 100644
--- a/src/image/script.c
+++ b/src/image/script.c
@@ -311,6 +311,7 @@ static int terminate_on_label_found ( int rc ) {
* @ret rc Return status code
*/
static int goto_exec ( int argc, char **argv ) {
+ struct image *image = current_image.image;
struct goto_options opts;
size_t saved_offset;
int rc;
@@ -320,7 +321,7 @@ static int goto_exec ( int argc, char **argv ) {
return rc;
/* Sanity check */
- if ( ! current_image ) {
+ if ( ! image ) {
rc = -ENOTTY;
printf ( "Not in a script: %s\n", strerror ( rc ) );
return rc;
@@ -331,10 +332,10 @@ static int goto_exec ( int argc, char **argv ) {
/* Find label */
saved_offset = script_offset;
- if ( ( rc = process_script ( current_image, goto_find_label,
+ if ( ( rc = process_script ( image, goto_find_label,
terminate_on_label_found ) ) != 0 ) {
script_offset = saved_offset;
- DBGC ( current_image, "[%04zx] No such label :%s\n",
+ DBGC ( image, "[%04zx] No such label :%s\n",
script_offset, goto_label );
return rc;
}
diff --git a/src/include/ctype.h b/src/include/ctype.h
index 0d79ecd1..6fefd5d7 100644
--- a/src/include/ctype.h
+++ b/src/include/ctype.h
@@ -10,6 +10,17 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/**
+ * Check if character is ASCII
+ *
+ * @v character Character
+ * @ret is_ascii Character is an ASCII character
+ */
+static inline int isascii ( int character ) {
+
+ return ( character <= '\x7f' );
+}
+
+/**
* Check if character is a decimal digit
*
* @v character ASCII character
diff --git a/src/include/ipxe/asn1.h b/src/include/ipxe/asn1.h
index fdf06f10..77429f3a 100644
--- a/src/include/ipxe/asn1.h
+++ b/src/include/ipxe/asn1.h
@@ -424,6 +424,8 @@ extern int asn1_digest_algorithm ( const struct asn1_cursor *cursor,
struct asn1_algorithm **algorithm );
extern int asn1_signature_algorithm ( const struct asn1_cursor *cursor,
struct asn1_algorithm **algorithm );
+extern int asn1_check_algorithm ( const struct asn1_cursor *cursor,
+ struct asn1_algorithm *expected );
extern int asn1_generalized_time ( const struct asn1_cursor *cursor,
time_t *time );
extern int asn1_grow ( struct asn1_builder *builder, size_t extra );
diff --git a/src/include/ipxe/dhcp.h b/src/include/ipxe/dhcp.h
index a1f9ee25..51349efd 100644
--- a/src/include/ipxe/dhcp.h
+++ b/src/include/ipxe/dhcp.h
@@ -86,6 +86,9 @@ struct dhcp_packet;
/** Maximum transmission unit */
#define DHCP_MTU 26
+/** NTP servers */
+#define DHCP_NTP_SERVERS 42
+
/** Vendor encapsulated options */
#define DHCP_VENDOR_ENCAP 43
diff --git a/src/include/ipxe/dummy_pio.h b/src/include/ipxe/dummy_pio.h
new file mode 100644
index 00000000..1cdabba1
--- /dev/null
+++ b/src/include/ipxe/dummy_pio.h
@@ -0,0 +1,64 @@
+#ifndef _IPXE_DUMMY_PIO_H
+#define _IPXE_DUMMY_PIO_H
+
+/** @file
+ *
+ * Dummy PIO reads and writes up to 32 bits
+ *
+ * There is no common standard for I/O-space access for non-x86 CPU
+ * families, and non-MMIO peripherals are vanishingly rare. Provide
+ * dummy implementations that will allow code to link and should cause
+ * drivers to simply fail to detect hardware at runtime.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#define DUMMY_INX( _prefix, _suffix, _type ) \
+static inline __always_inline _type \
+IOAPI_INLINE ( _prefix, in ## _suffix ) ( volatile _type *io_addr __unused) { \
+ return ~( (_type) 0 ); \
+} \
+static inline __always_inline void \
+IOAPI_INLINE ( _prefix, ins ## _suffix ) ( volatile _type *io_addr __unused, \
+ _type *data, unsigned int count ) {\
+ memset ( data, 0xff, count * sizeof ( *data ) ); \
+}
+
+#define DUMMY_OUTX( _prefix, _suffix, _type ) \
+static inline __always_inline void \
+IOAPI_INLINE ( _prefix, out ## _suffix ) ( _type data __unused, \
+ volatile _type *io_addr __unused ){\
+ /* Do nothing */ \
+} \
+static inline __always_inline void \
+IOAPI_INLINE ( _prefix, outs ## _suffix ) ( volatile _type *io_addr __unused, \
+ const _type *data __unused, \
+ unsigned int count __unused ) { \
+ /* Do nothing */ \
+}
+
+#define DUMMY_IODELAY( _prefix ) \
+static inline __always_inline void \
+IOAPI_INLINE ( _prefix, iodelay ) ( void ) { \
+ /* Nothing to do */ \
+}
+
+#define DUMMY_PIO( _prefix ) \
+ DUMMY_INX ( _prefix, b, uint8_t ); \
+ DUMMY_INX ( _prefix, w, uint16_t ); \
+ DUMMY_INX ( _prefix, l, uint32_t ); \
+ DUMMY_OUTX ( _prefix, b, uint8_t ); \
+ DUMMY_OUTX ( _prefix, w, uint16_t ); \
+ DUMMY_OUTX ( _prefix, l, uint32_t ); \
+ DUMMY_IODELAY ( _prefix );
+
+#define PROVIDE_DUMMY_PIO( _prefix ) \
+ PROVIDE_IOAPI_INLINE ( _prefix, inb ); \
+ PROVIDE_IOAPI_INLINE ( _prefix, inw ); \
+ PROVIDE_IOAPI_INLINE ( _prefix, inl ); \
+ PROVIDE_IOAPI_INLINE ( _prefix, outb ); \
+ PROVIDE_IOAPI_INLINE ( _prefix, outw ); \
+ PROVIDE_IOAPI_INLINE ( _prefix, outl ); \
+ PROVIDE_IOAPI_INLINE ( _prefix, iodelay );
+
+#endif /* _IPXE_DUMMY_PIO_H */
diff --git a/src/include/ipxe/eap.h b/src/include/ipxe/eap.h
index 6fe70189..e5f60655 100644
--- a/src/include/ipxe/eap.h
+++ b/src/include/ipxe/eap.h
@@ -64,6 +64,25 @@ union eap_packet {
*/
#define EAP_BLOCK_TIMEOUT ( 45 * TICKS_PER_SEC )
-extern int eap_rx ( struct net_device *netdev, const void *data, size_t len );
+/** An EAP supplicant */
+struct eap_supplicant {
+ /** Network device */
+ struct net_device *netdev;
+ /** Authentication outcome is final */
+ int done;
+ /**
+ * Transmit EAP response
+ *
+ * @v supplicant EAP supplicant
+ * @v data Response data
+ * @v len Length of response data
+ * @ret rc Return status code
+ */
+ int ( * tx ) ( struct eap_supplicant *supplicant,
+ const void *data, size_t len );
+};
+
+extern int eap_rx ( struct eap_supplicant *supplicant,
+ const void *data, size_t len );
#endif /* _IPXE_EAP_H */
diff --git a/src/include/ipxe/eapol.h b/src/include/ipxe/eapol.h
index 952d6c75..d4ea3920 100644
--- a/src/include/ipxe/eapol.h
+++ b/src/include/ipxe/eapol.h
@@ -12,6 +12,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <ipxe/netdevice.h>
#include <ipxe/tables.h>
+#include <ipxe/eap.h>
/** EAPoL header */
struct eapol_header {
@@ -29,9 +30,23 @@ struct eapol_header {
/** EAPoL-encapsulated EAP packets */
#define EAPOL_TYPE_EAP 0
+/** EAPoL start */
+#define EAPOL_TYPE_START 1
+
/** EAPoL key */
#define EAPOL_TYPE_KEY 5
+/** An EAPoL supplicant */
+struct eapol_supplicant {
+ /** EAP supplicant */
+ struct eap_supplicant eap;
+ /** EAPoL-Start retransmission timer */
+ struct retry_timer timer;
+};
+
+/** Delay between EAPoL-Start packets */
+#define EAPOL_START_INTERVAL ( 2 * TICKS_PER_SEC )
+
/** An EAPoL handler */
struct eapol_handler {
/** Type */
@@ -39,15 +54,15 @@ struct eapol_handler {
/**
* Process received packet
*
+ * @v supplicant EAPoL supplicant
* @v iobuf I/O buffer
- * @v netdev Network device
* @v ll_source Link-layer source address
* @ret rc Return status code
*
* This method takes ownership of the I/O buffer.
*/
- int ( * rx ) ( struct io_buffer *iobuf, struct net_device *netdev,
- const void *ll_source );
+ int ( * rx ) ( struct eapol_supplicant *supplicant,
+ struct io_buffer *iobuf, const void *ll_source );
};
/** EAPoL handler table */
diff --git a/src/include/ipxe/efi/AArch64/ProcessorBind.h b/src/include/ipxe/efi/AArch64/ProcessorBind.h
index d0cb86a4..3a7f7746 100644
--- a/src/include/ipxe/efi/AArch64/ProcessorBind.h
+++ b/src/include/ipxe/efi/AArch64/ProcessorBind.h
@@ -188,6 +188,40 @@ typedef INT64 INTN;
#define GCC_ASM_IMPORT(func__) \
.extern _CONCATENATE (__USER_LABEL_PREFIX__, func__)
+ #if defined (__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT == 1
+#define AARCH64_BTI_NOTE() \
+ .ifndef .Lgnu_bti_notesize ;\
+ .pushsection .note.gnu.property, "a" ;\
+ .set NT_GNU_PROPERTY_TYPE_0, 0x5 ;\
+ .set GNU_PROPERTY_AARCH64_FEATURE_1_AND, 0xc0000000 ;\
+ .set GNU_PROPERTY_AARCH64_FEATURE_1_BTI, 0x1 ;\
+ .align 3 ;\
+ .long .Lnamesize ;\
+ .long .Lgnu_bti_notesize ;\
+ .long NT_GNU_PROPERTY_TYPE_0 ;\
+0: .asciz "GNU" ;\
+ .set .Lnamesize, . - 0b ;\
+ .align 3 ;\
+1: .long GNU_PROPERTY_AARCH64_FEATURE_1_AND ;\
+ .long .Lvalsize ;\
+2: .long GNU_PROPERTY_AARCH64_FEATURE_1_BTI ;\
+ .set .Lvalsize, . - 2b ;\
+ .align 3 ;\
+ .set .Lgnu_bti_notesize, . - 1b ;\
+ .popsection ;\
+ .endif
+
+#define AARCH64_BTI(__type) \
+ AARCH64_BTI_NOTE() ;\
+ bti __type
+
+ #endif
+
+#endif
+
+#ifndef AARCH64_BTI
+#define AARCH64_BTI_NOTE()
+#define AARCH64_BTI(__type)
#endif
/**
diff --git a/src/include/ipxe/efi/Base.h b/src/include/ipxe/efi/Base.h
index b0093c63..e76013c1 100644
--- a/src/include/ipxe/efi/Base.h
+++ b/src/include/ipxe/efi/Base.h
@@ -761,6 +761,40 @@ typedef UINTN *BASE_LIST;
#endif
/**
+ Returns the alignment requirement of a type.
+
+ @param TYPE The name of the type to retrieve the alignment requirement of.
+
+ @return Alignment requirement, in Bytes, of TYPE.
+**/
+#if defined (__cplusplus)
+//
+// Standard C++ operator.
+//
+#define ALIGNOF(TYPE) alignof (TYPE)
+#elif defined (__GNUC__) || defined (__clang__) || (defined (_MSC_VER) && _MSC_VER >= 1900)
+//
+// All supported versions of GCC and Clang, as well as MSVC 2015 and later,
+// support the standard operator _Alignof.
+//
+#define ALIGNOF(TYPE) _Alignof (TYPE)
+#elif defined (_MSC_EXTENSIONS)
+//
+// Earlier versions of MSVC, at least MSVC 2008 and later, support the vendor
+// extension __alignof.
+//
+#define ALIGNOF(TYPE) __alignof (TYPE)
+#else
+//
+// For compilers that do not support inbuilt alignof operators, use OFFSET_OF.
+// CHAR8 is known to have both a size and an alignment requirement of 1 Byte.
+// As such, A must be located exactly at the offset equal to its alignment
+// requirement.
+//
+#define ALIGNOF(TYPE) OFFSET_OF (struct { CHAR8 C; TYPE A; }, A)
+#endif
+
+/**
Portable definition for compile time assertions.
Equivalent to C11 static_assert macro from assert.h.
@@ -795,12 +829,27 @@ STATIC_ASSERT (sizeof (CHAR16) == 2, "sizeof (CHAR16) does not meet UEFI Specif
STATIC_ASSERT (sizeof (L'A') == 2, "sizeof (L'A') does not meet UEFI Specification Data Type requirements");
STATIC_ASSERT (sizeof (L"A") == 4, "sizeof (L\"A\") does not meet UEFI Specification Data Type requirements");
+STATIC_ASSERT (ALIGNOF (BOOLEAN) == sizeof (BOOLEAN), "Alignment of BOOLEAN does not meet UEFI Specification Data Type requirements");
+STATIC_ASSERT (ALIGNOF (INT8) == sizeof (INT8), "Alignment of INT8 does not meet UEFI Specification Data Type requirements");
+STATIC_ASSERT (ALIGNOF (UINT8) == sizeof (UINT8), "Alignment of INT16 does not meet UEFI Specification Data Type requirements");
+STATIC_ASSERT (ALIGNOF (INT16) == sizeof (INT16), "Alignment of INT16 does not meet UEFI Specification Data Type requirements");
+STATIC_ASSERT (ALIGNOF (UINT16) == sizeof (UINT16), "Alignment of UINT16 does not meet UEFI Specification Data Type requirements");
+STATIC_ASSERT (ALIGNOF (INT32) == sizeof (INT32), "Alignment of INT32 does not meet UEFI Specification Data Type requirements");
+STATIC_ASSERT (ALIGNOF (UINT32) == sizeof (UINT32), "Alignment of UINT32 does not meet UEFI Specification Data Type requirements");
+STATIC_ASSERT (ALIGNOF (INT64) == sizeof (INT64), "Alignment of INT64 does not meet UEFI Specification Data Type requirements");
+STATIC_ASSERT (ALIGNOF (UINT64) == sizeof (UINT64), "Alignment of UINT64 does not meet UEFI Specification Data Type requirements");
+STATIC_ASSERT (ALIGNOF (CHAR8) == sizeof (CHAR8), "Alignment of CHAR8 does not meet UEFI Specification Data Type requirements");
+STATIC_ASSERT (ALIGNOF (CHAR16) == sizeof (CHAR16), "Alignment of CHAR16 does not meet UEFI Specification Data Type requirements");
+STATIC_ASSERT (ALIGNOF (INTN) == sizeof (INTN), "Alignment of INTN does not meet UEFI Specification Data Type requirements");
+STATIC_ASSERT (ALIGNOF (UINTN) == sizeof (UINTN), "Alignment of UINTN does not meet UEFI Specification Data Type requirements");
+STATIC_ASSERT (ALIGNOF (VOID *) == sizeof (VOID *), "Alignment of VOID * does not meet UEFI Specification Data Type requirements");
+
//
// The following three enum types are used to verify that the compiler
// configuration for enum types is compliant with Section 2.3.1 of the
-// UEFI 2.3 Specification. These enum types and enum values are not
-// intended to be used. A prefix of '__' is used avoid conflicts with
-// other types.
+// UEFI 2.3.1 Errata C Specification. These enum types and enum values
+// are not intended to be used. A prefix of '__' is used avoid
+// conflicts with other types.
//
typedef enum {
__VerifyUint8EnumValue = 0xff
@@ -811,12 +860,16 @@ typedef enum {
} __VERIFY_UINT16_ENUM_SIZE;
typedef enum {
- __VerifyUint32EnumValue = 0xffffffff
-} __VERIFY_UINT32_ENUM_SIZE;
+ __VerifyInt32EnumValue = 0x7fffffff
+} __VERIFY_INT32_ENUM_SIZE;
STATIC_ASSERT (sizeof (__VERIFY_UINT8_ENUM_SIZE) == 4, "Size of enum does not meet UEFI Specification Data Type requirements");
STATIC_ASSERT (sizeof (__VERIFY_UINT16_ENUM_SIZE) == 4, "Size of enum does not meet UEFI Specification Data Type requirements");
-STATIC_ASSERT (sizeof (__VERIFY_UINT32_ENUM_SIZE) == 4, "Size of enum does not meet UEFI Specification Data Type requirements");
+STATIC_ASSERT (sizeof (__VERIFY_INT32_ENUM_SIZE) == 4, "Size of enum does not meet UEFI Specification Data Type requirements");
+
+STATIC_ASSERT (ALIGNOF (__VERIFY_UINT8_ENUM_SIZE) == sizeof (__VERIFY_UINT8_ENUM_SIZE), "Alignment of enum does not meet UEFI Specification Data Type requirements");
+STATIC_ASSERT (ALIGNOF (__VERIFY_UINT16_ENUM_SIZE) == sizeof (__VERIFY_UINT16_ENUM_SIZE), "Alignment of enum does not meet UEFI Specification Data Type requirements");
+STATIC_ASSERT (ALIGNOF (__VERIFY_INT32_ENUM_SIZE) == sizeof (__VERIFY_INT32_ENUM_SIZE), "Alignment of enum does not meet UEFI Specification Data Type requirements");
/**
Macro that returns a pointer to the data structure that contains a specified field of
@@ -840,6 +893,49 @@ STATIC_ASSERT (sizeof (__VERIFY_UINT32_ENUM_SIZE) == 4, "Size of enum does not m
#define BASE_CR(Record, TYPE, Field) ((TYPE *) ((CHAR8 *) (Record) - OFFSET_OF (TYPE, Field)))
/**
+ Checks whether a value is a power of two.
+
+ @param Value The value to check.
+
+ @retval TRUE Value is a power of two.
+ @retval FALSE Value is not a power of two.
+**/
+#define IS_POW2(Value) ((Value) != 0U && ((Value) & ((Value) - 1U)) == 0U)
+
+/**
+ Checks whether a value is aligned by a specified alignment.
+
+ @param Value The value to check.
+ @param Alignment The alignment boundary used to check against.
+
+ @retval TRUE Value is aligned by Alignment.
+ @retval FALSE Value is not aligned by Alignment.
+**/
+#define IS_ALIGNED(Value, Alignment) (((Value) & ((Alignment) - 1U)) == 0U)
+
+/**
+ Checks whether a pointer or address is aligned by a specified alignment.
+
+ @param Address The pointer or address to check.
+ @param Alignment The alignment boundary used to check against.
+
+ @retval TRUE Address is aligned by Alignment.
+ @retval FALSE Address is not aligned by Alignment.
+**/
+#define ADDRESS_IS_ALIGNED(Address, Alignment) IS_ALIGNED ((UINTN) (Address), Alignment)
+
+/**
+ Determines the addend to add to a value to round it up to the next boundary of
+ a specified alignment.
+
+ @param Value The value to round up.
+ @param Alignment The alignment boundary used to return the addend.
+
+ @return Addend to round Value up to alignment boundary Alignment.
+**/
+#define ALIGN_VALUE_ADDEND(Value, Alignment) (((Alignment) - (Value)) & ((Alignment) - 1U))
+
+/**
Rounds a value up to the next boundary using a specified alignment.
This function rounds Value up to the next boundary using the specified Alignment.
@@ -851,7 +947,7 @@ STATIC_ASSERT (sizeof (__VERIFY_UINT32_ENUM_SIZE) == 4, "Size of enum does not m
@return A value up to the next boundary.
**/
-#define ALIGN_VALUE(Value, Alignment) ((Value) + (((Alignment) - (Value)) & ((Alignment) - 1)))
+#define ALIGN_VALUE(Value, Alignment) ((Value) + ALIGN_VALUE_ADDEND (Value, Alignment))
/**
Adjust a pointer by adding the minimum offset required for it to be aligned on
diff --git a/src/include/ipxe/efi/Ia32/ProcessorBind.h b/src/include/ipxe/efi/Ia32/ProcessorBind.h
index 5e3fb92d..b922597f 100644
--- a/src/include/ipxe/efi/Ia32/ProcessorBind.h
+++ b/src/include/ipxe/efi/Ia32/ProcessorBind.h
@@ -91,18 +91,14 @@ FILE_LICENCE ( BSD2_PATENT );
#if defined (_MSC_VER) && _MSC_VER >= 1800
//
-// Disable these warnings for VS2013.
-//
-
-//
// This warning is for potentially uninitialized local variable, and it may cause false
-// positive issues in VS2013 and VS2015 build
+// positive issues in VS2015 build
//
#pragma warning ( disable : 4701 )
//
// This warning is for potentially uninitialized local pointer variable, and it may cause
-// false positive issues in VS2013 and VS2015 build
+// false positive issues in VS2015 build
//
#pragma warning ( disable : 4703 )
diff --git a/src/include/ipxe/efi/IndustryStandard/PeImage.h b/src/include/ipxe/efi/IndustryStandard/PeImage.h
index 0e0f54f8..401e961c 100644
--- a/src/include/ipxe/efi/IndustryStandard/PeImage.h
+++ b/src/include/ipxe/efi/IndustryStandard/PeImage.h
@@ -103,6 +103,7 @@ typedef struct {
#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE BIT1 ///< 0x0002 File is executable (i.e. no unresolved externel references).
#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED BIT2 ///< 0x0004 Line numbers stripped from file.
#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED BIT3 ///< 0x0008 Local symbols stripped from file.
+#define EFI_IMAGE_FILE_LARGE_ADDRESS_AWARE BIT5 ///< 0x0020 Supports addresses > 2-GB
#define EFI_IMAGE_FILE_BYTES_REVERSED_LO BIT7 ///< 0x0080 Bytes of machine word are reversed.
#define EFI_IMAGE_FILE_32BIT_MACHINE BIT8 ///< 0x0100 32 bit word machine.
#define EFI_IMAGE_FILE_DEBUG_STRIPPED BIT9 ///< 0x0200 Debugging info stripped from file in .DBG file.
@@ -579,6 +580,13 @@ typedef struct {
UINT32 AddressOfNameOrdinals;
} EFI_IMAGE_EXPORT_DIRECTORY;
+//
+// Based export types.
+//
+#define EFI_IMAGE_EXPORT_ORDINAL_BASE 1
+#define EFI_IMAGE_EXPORT_ADDR_SIZE 4
+#define EFI_IMAGE_EXPORT_ORDINAL_SIZE 2
+
///
/// Hint/Name Table.
///
@@ -627,7 +635,8 @@ typedef struct {
UINT32 FileOffset; ///< The file pointer to the debug data.
} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY;
-#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2 ///< The Visual C++ debug information.
+#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2 ///< The Visual C++ debug information.
+#define EFI_IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS 20
///
/// Debug Data Structure defined in Microsoft C++.
@@ -671,6 +680,39 @@ typedef struct {
//
} EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY;
+// avoid conflict with windows header files
+#ifndef RUNTIME_FUNCTION_INDIRECT
+
+//
+// .pdata entries for X64
+//
+typedef struct {
+ UINT32 FunctionStartAddress;
+ UINT32 FunctionEndAddress;
+ UINT32 UnwindInfoAddress;
+} RUNTIME_FUNCTION;
+
+#endif
+
+typedef struct {
+ UINT8 Version : 3;
+ UINT8 Flags : 5;
+ UINT8 SizeOfProlog;
+ UINT8 CountOfUnwindCodes;
+ UINT8 FrameRegister : 4;
+ UINT8 FrameRegisterOffset : 4;
+} UNWIND_INFO;
+
+///
+/// Extended DLL Characteristics
+///
+#define EFI_IMAGE_DLLCHARACTERISTICS_EX_CET_COMPAT 0x0001
+#define EFI_IMAGE_DLLCHARACTERISTICS_EX_FORWARD_CFI_COMPAT 0x0040
+
+typedef struct {
+ UINT32 DllCharacteristicsEx;
+} EFI_IMAGE_DEBUG_EX_DLLCHARACTERISTICS_ENTRY;
+
///
/// Resource format.
///
diff --git a/src/include/ipxe/efi/Library/BaseLib.h b/src/include/ipxe/efi/Library/BaseLib.h
index 416ca00d..e17f3da2 100644
--- a/src/include/ipxe/efi/Library/BaseLib.h
+++ b/src/include/ipxe/efi/Library/BaseLib.h
@@ -153,6 +153,56 @@ typedef struct {
#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 8
+VOID
+RiscVSetSupervisorScratch (
+ IN UINT64
+ );
+
+UINT64
+RiscVGetSupervisorScratch (
+ VOID
+ );
+
+VOID
+RiscVSetSupervisorStvec (
+ IN UINT64
+ );
+
+UINT64
+RiscVGetSupervisorStvec (
+ VOID
+ );
+
+UINT64
+RiscVGetSupervisorTrapCause (
+ VOID
+ );
+
+VOID
+RiscVSetSupervisorAddressTranslationRegister (
+ IN UINT64
+ );
+
+UINT64
+RiscVReadTimer (
+ VOID
+ );
+
+VOID
+RiscVEnableTimerInterrupt (
+ VOID
+ );
+
+VOID
+RiscVDisableTimerInterrupt (
+ VOID
+ );
+
+VOID
+RiscVClearPendingTimerInterrupt (
+ VOID
+ );
+
#endif // defined (MDE_CPU_RISCV64)
#if defined (MDE_CPU_LOONGARCH64)
diff --git a/src/include/ipxe/efi/Protocol/DebugSupport.h b/src/include/ipxe/efi/Protocol/DebugSupport.h
index 1b28b0ed..453ea975 100644
--- a/src/include/ipxe/efi/Protocol/DebugSupport.h
+++ b/src/include/ipxe/efi/Protocol/DebugSupport.h
@@ -615,11 +615,34 @@ typedef struct {
#define EXCEPT_RISCV_STORE_AMO_ACCESS_FAULT 7
#define EXCEPT_RISCV_ENV_CALL_FROM_UMODE 8
#define EXCEPT_RISCV_ENV_CALL_FROM_SMODE 9
-#define EXCEPT_RISCV_ENV_CALL_FROM_HMODE 10
+#define EXCEPT_RISCV_ENV_CALL_FROM_VS_MODE 10
#define EXCEPT_RISCV_ENV_CALL_FROM_MMODE 11
-
-#define EXCEPT_RISCV_SOFTWARE_INT 0x0
-#define EXCEPT_RISCV_TIMER_INT 0x1
+#define EXCEPT_RISCV_INST_ACCESS_PAGE_FAULT 12
+#define EXCEPT_RISCV_LOAD_ACCESS_PAGE_FAULT 13
+#define EXCEPT_RISCV_14 14
+#define EXCEPT_RISCV_STORE_ACCESS_PAGE_FAULT 15
+#define EXCEPT_RISCV_16 16
+#define EXCEPT_RISCV_17 17
+#define EXCEPT_RISCV_18 18
+#define EXCEPT_RISCV_19 19
+#define EXCEPT_RISCV_INST_GUEST_PAGE_FAULT 20
+#define EXCEPT_RISCV_LOAD_GUEST_PAGE_FAULT 21
+#define EXCEPT_RISCV_VIRTUAL_INSTRUCTION 22
+#define EXCEPT_RISCV_STORE_GUEST_PAGE_FAULT 23
+#define EXCEPT_RISCV_MAX_EXCEPTIONS (EXCEPT_RISCV_STORE_GUEST_PAGE_FAULT)
+
+///
+/// RISC-V processor exception types for interrupts.
+///
+#define EXCEPT_RISCV_IS_IRQ(x) ((x & 0x8000000000000000UL) != 0)
+#define EXCEPT_RISCV_IRQ_INDEX(x) (x & 0x7FFFFFFFFFFFFFFFUL)
+#define EXCEPT_RISCV_IRQ_0 0x8000000000000000UL
+#define EXCEPT_RISCV_IRQ_SOFT_FROM_SMODE 0x8000000000000001UL
+#define EXCEPT_RISCV_IRQ_SOFT_FROM_VSMODE 0x8000000000000002UL
+#define EXCEPT_RISCV_IRQ_SOFT_FROM_MMODE 0x8000000000000003UL
+#define EXCEPT_RISCV_IRQ_4 0x8000000000000004UL
+#define EXCEPT_RISCV_IRQ_TIMER_FROM_SMODE 0x8000000000000005UL
+#define EXCEPT_RISCV_MAX_IRQS (EXCEPT_RISCV_IRQ_INDEX(EXCEPT_RISCV_IRQ_TIMER_FROM_SMODE))
typedef struct {
UINT64 X0;
@@ -654,6 +677,9 @@ typedef struct {
UINT64 X29;
UINT64 X30;
UINT64 X31;
+ UINT64 SEPC;
+ UINT32 SSTATUS;
+ UINT32 STVAL;
} EFI_SYSTEM_CONTEXT_RISCV64;
//
diff --git a/src/include/ipxe/efi/Protocol/Dhcp6.h b/src/include/ipxe/efi/Protocol/Dhcp6.h
new file mode 100644
index 00000000..19f59086
--- /dev/null
+++ b/src/include/ipxe/efi/Protocol/Dhcp6.h
@@ -0,0 +1,782 @@
+/** @file
+ UEFI Dynamic Host Configuration Protocol 6 Definition, which is used to get IPv6
+ addresses and other configuration parameters from DHCPv6 servers.
+
+ Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Revision Reference:
+ This Protocol is introduced in UEFI Specification 2.2
+
+**/
+
+#ifndef __EFI_DHCP6_PROTOCOL_H__
+#define __EFI_DHCP6_PROTOCOL_H__
+
+FILE_LICENCE ( BSD2_PATENT );
+
+#define EFI_DHCP6_PROTOCOL_GUID \
+ { \
+ 0x87c8bad7, 0x595, 0x4053, {0x82, 0x97, 0xde, 0xde, 0x39, 0x5f, 0x5d, 0x5b } \
+ }
+
+#define EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID \
+ { \
+ 0x9fb9a8a1, 0x2f4a, 0x43a6, {0x88, 0x9c, 0xd0, 0xf7, 0xb6, 0xc4, 0x7a, 0xd5 } \
+ }
+
+typedef struct _EFI_DHCP6_PROTOCOL EFI_DHCP6_PROTOCOL;
+
+typedef enum {
+ ///
+ /// The EFI DHCPv6 Protocol instance is configured, and start() needs
+ /// to be called
+ ///
+ Dhcp6Init = 0x0,
+ ///
+ /// A Solicit packet is sent out to discover DHCPv6 server, and the EFI
+ /// DHCPv6 Protocol instance is collecting Advertise packets.
+ ///
+ Dhcp6Selecting = 0x1,
+ ///
+ /// A Request is sent out to the DHCPv6 server, and the EFI DHCPv6
+ /// Protocol instance is waiting for Reply packet.
+ ///
+ Dhcp6Requesting = 0x2,
+ ///
+ /// A Decline packet is sent out to indicate one or more addresses of the
+ /// configured IA are in use by another node, and the EFI DHCPv6.
+ /// Protocol instance is waiting for Reply packet.
+ ///
+ Dhcp6Declining = 0x3,
+ ///
+ /// A Confirm packet is sent out to confirm the IPv6 addresses of the
+ /// configured IA, and the EFI DHCPv6 Protocol instance is waiting for Reply packet.
+ ///
+ Dhcp6Confirming = 0x4,
+ ///
+ /// A Release packet is sent out to release one or more IPv6 addresses of
+ /// the configured IA, and the EFI DHCPv6 Protocol instance is waiting for Reply packet.
+ ///
+ Dhcp6Releasing = 0x5,
+ ///
+ /// The DHCPv6 S.A.R.R process is completed for the configured IA.
+ ///
+ Dhcp6Bound = 0x6,
+ ///
+ /// A Renew packet is sent out to extend lifetime for the IPv6 addresses of
+ /// the configured IA, and the EFI DHCPv6 Protocol instance is waiting for Reply packet.
+ ///
+ Dhcp6Renewing = 0x7,
+ ///
+ /// A Rebind packet is sent out to extend lifetime for the IPv6 addresses of
+ /// the configured IA, and the EFI DHCPv6 Protocol instance is waiting for Reply packet.
+ ///
+ Dhcp6Rebinding = 0x8
+} EFI_DHCP6_STATE;
+
+typedef enum {
+ ///
+ /// A Solicit packet is about to be sent. The packet is passed to Dhcp6Callback and
+ /// can be modified or replaced in Dhcp6Callback.
+ ///
+ Dhcp6SendSolicit = 0x0,
+ ///
+ /// An Advertise packet is received and will be passed to Dhcp6Callback.
+ ///
+ Dhcp6RcvdAdvertise = 0x1,
+ ///
+ /// It is time for Dhcp6Callback to determine whether select the default Advertise
+ /// packet by RFC 3315 policy, or overwrite it by specific user policy.
+ ///
+ Dhcp6SelectAdvertise = 0x2,
+ ///
+ /// A Request packet is about to be sent. The packet is passed to Dhcp6Callback and
+ /// can be modified or replaced in Dhcp6Callback.
+ ///
+ Dhcp6SendRequest = 0x3,
+ ///
+ /// A Reply packet is received and will be passed to Dhcp6Callback.
+ ///
+ Dhcp6RcvdReply = 0x4,
+ ///
+ /// A Reconfigure packet is received and will be passed to Dhcp6Callback.
+ ///
+ Dhcp6RcvdReconfigure = 0x5,
+ ///
+ /// A Decline packet is about to be sent. The packet is passed to Dhcp6Callback and
+ /// can be modified or replaced in Dhcp6Callback.
+ ///
+ Dhcp6SendDecline = 0x6,
+ ///
+ /// A Confirm packet is about to be sent. The packet is passed to Dhcp6Callback and
+ /// can be modified or replaced in Dhcp6Callback.
+ ///
+ Dhcp6SendConfirm = 0x7,
+ ///
+ /// A Release packet is about to be sent. The packet is passed to Dhcp6Callback and
+ /// can be modified or replaced in Dhcp6Callback.
+ ///
+ Dhcp6SendRelease = 0x8,
+ ///
+ /// A Renew packet is about to be sent. The packet is passed to Dhcp6Callback and
+ /// can be modified or replaced in Dhcp6Callback.
+ ///
+ Dhcp6EnterRenewing = 0x9,
+ ///
+ /// A Rebind packet is about to be sent. The packet is passed to Dhcp6Callback and
+ /// can be modified or replaced in Dhcp6Callback.
+ ///
+ Dhcp6EnterRebinding = 0xa
+} EFI_DHCP6_EVENT;
+
+///
+/// An IA which carries assigned not temporary address.
+///
+#define EFI_DHCP6_IA_TYPE_NA 3
+///
+/// An IA which carries assigned temporary address.
+///
+#define EFI_DHCP6_IA_TYPE_TA 4
+
+#pragma pack(1)
+///
+/// EFI_DHCP6_PACKET_OPTION
+/// defines the format of the DHCPv6 option, See RFC 3315 for more information.
+/// This data structure is used to reference option data that is packed in the DHCPv6 packet.
+///
+typedef struct {
+ ///
+ /// The DHCPv6 option code, stored in network order.
+ ///
+ UINT16 OpCode;
+ ///
+ /// Length of the DHCPv6 option data, stored in network order.
+ /// From the first byte to the last byte of the Data field.
+ ///
+ UINT16 OpLen;
+ ///
+ /// The data for the DHCPv6 option, stored in network order.
+ ///
+ UINT8 Data[1];
+} EFI_DHCP6_PACKET_OPTION;
+
+///
+/// EFI_DHCP6_HEADER
+/// defines the format of the DHCPv6 header. See RFC 3315 for more information.
+///
+typedef struct {
+ ///
+ /// The DHCPv6 transaction ID.
+ ///
+ UINT32 MessageType : 8;
+ ///
+ /// The DHCPv6 message type.
+ ///
+ UINT32 TransactionId : 24;
+} EFI_DHCP6_HEADER;
+
+///
+/// EFI_DHCP6_PACKET
+/// defines the format of the DHCPv6 packet. See RFC 3315 for more information.
+///
+typedef struct {
+ ///
+ /// Size of the EFI_DHCP6_PACKET buffer.
+ ///
+ UINT32 Size;
+ ///
+ /// Length of the EFI_DHCP6_PACKET from the first byte of the Header field to the last
+ /// byte of the Option[] field.
+ ///
+ UINT32 Length;
+ struct {
+ ///
+ /// The DHCPv6 packet header.
+ ///
+ EFI_DHCP6_HEADER Header;
+ ///
+ /// Start of the DHCPv6 packed option data.
+ ///
+ UINT8 Option[1];
+ } Dhcp6;
+} EFI_DHCP6_PACKET;
+
+#pragma pack()
+
+typedef struct {
+ ///
+ /// Length of DUID in octects.
+ ///
+ UINT16 Length;
+ ///
+ /// Array of DUID octects.
+ ///
+ UINT8 Duid[1];
+} EFI_DHCP6_DUID;
+
+typedef struct {
+ ///
+ /// Initial retransmission timeout.
+ ///
+ UINT32 Irt;
+ ///
+ /// Maximum retransmission count for one packet. If Mrc is zero, there's no upper limit
+ /// for retransmission count.
+ ///
+ UINT32 Mrc;
+ ///
+ /// Maximum retransmission timeout for each retry. It's the upper bound of the number of
+ /// retransmission timeout. If Mrt is zero, there is no upper limit for retransmission
+ /// timeout.
+ ///
+ UINT32 Mrt;
+ ///
+ /// Maximum retransmission duration for one packet. It's the upper bound of the numbers
+ /// the client may retransmit a message. If Mrd is zero, there's no upper limit for
+ /// retransmission duration.
+ ///
+ UINT32 Mrd;
+} EFI_DHCP6_RETRANSMISSION;
+
+typedef struct {
+ ///
+ /// The IPv6 address.
+ ///
+ EFI_IPv6_ADDRESS IpAddress;
+ ///
+ /// The preferred lifetime in unit of seconds for the IPv6 address.
+ ///
+ UINT32 PreferredLifetime;
+ ///
+ /// The valid lifetime in unit of seconds for the IPv6 address.
+ ///
+ UINT32 ValidLifetime;
+} EFI_DHCP6_IA_ADDRESS;
+
+typedef struct {
+ UINT16 Type; ///< Type for an IA.
+ UINT32 IaId; ///< The identifier for an IA.
+} EFI_DHCP6_IA_DESCRIPTOR;
+
+typedef struct {
+ ///
+ /// The descriptor for IA.
+ ///
+ EFI_DHCP6_IA_DESCRIPTOR Descriptor;
+ ///
+ /// The state of the configured IA.
+ ///
+ EFI_DHCP6_STATE State;
+ ///
+ /// Pointer to the cached latest Reply packet. May be NULL if no packet is cached.
+ ///
+ EFI_DHCP6_PACKET *ReplyPacket;
+ ///
+ /// Number of IPv6 addresses of the configured IA.
+ ///
+ UINT32 IaAddressCount;
+ ///
+ /// List of the IPv6 addresses of the configured IA. When the state of the configured IA is
+ /// in Dhcp6Bound, Dhcp6Renewing and Dhcp6Rebinding, the IPv6 addresses are usable.
+ ///
+ EFI_DHCP6_IA_ADDRESS IaAddress[1];
+} EFI_DHCP6_IA;
+
+typedef struct {
+ ///
+ /// Pointer to the DHCPv6 unique identifier. The caller is responsible for freeing this buffer.
+ ///
+ EFI_DHCP6_DUID *ClientId;
+ ///
+ /// Pointer to the configured IA of current instance. The caller can free this buffer after
+ /// using it.
+ ///
+ EFI_DHCP6_IA *Ia;
+} EFI_DHCP6_MODE_DATA;
+
+/**
+ EFI_DHCP6_CALLBACK is provided by the consumer of the EFI DHCPv6 Protocol instance to
+ intercept events that occurs in the DHCPv6 S.A.R.R process.
+
+ @param[in] This Pointer to the EFI_DHCP6_PROTOCOL instance that is used to configure this
+ callback function.
+ @param[in] Context Pointer to the context that is initialized by EFI_DHCP6_PROTOCOL.Configure().
+ @param[in] CurrentState The current state of the configured IA.
+ @param[in] Dhcp6Event The event that occurs in the current state, which usually means a state transition.
+ @param[in] Packet Pointer to the DHCPv6 packet that is about to be sent or has been received.
+ The EFI DHCPv6 Protocol instance is responsible for freeing the buffer.
+ @param[out] NewPacket Pointer to the new DHCPv6 packet to overwrite the Packet. NewPacket can not
+ share the buffer with Packet. If *NewPacket is not NULL, the EFI DHCPv6
+ Protocol instance is responsible for freeing the buffer.
+
+ @retval EFI_SUCCESS Tell the EFI DHCPv6 Protocol instance to continue the DHCPv6 S.A.R.R process.
+ @retval EFI_ABORTED Tell the EFI DHCPv6 Protocol instance to abort the DHCPv6 S.A.R.R process,
+ and the state of the configured IA will be transferred to Dhcp6Init.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DHCP6_CALLBACK)(
+ IN EFI_DHCP6_PROTOCOL *This,
+ IN VOID *Context,
+ IN EFI_DHCP6_STATE CurrentState,
+ IN EFI_DHCP6_EVENT Dhcp6Event,
+ IN EFI_DHCP6_PACKET *Packet,
+ OUT EFI_DHCP6_PACKET **NewPacket OPTIONAL
+ );
+
+typedef struct {
+ ///
+ /// The callback function is to intercept various events that occur in the DHCPv6 S.A.R.R
+ /// process. Set to NULL to ignore all those events.
+ ///
+ EFI_DHCP6_CALLBACK Dhcp6Callback;
+ ///
+ /// Pointer to the context that will be passed to Dhcp6Callback.
+ ///
+ VOID *CallbackContext;
+ ///
+ /// Number of the DHCPv6 options in the OptionList.
+ ///
+ UINT32 OptionCount;
+ ///
+ /// List of the DHCPv6 options to be included in Solicit and Request packet. The buffer
+ /// can be freed after EFI_DHCP6_PROTOCOL.Configure() returns. Ignored if
+ /// OptionCount is zero. OptionList should not contain Client Identifier option
+ /// and any IA option, which will be appended by EFI DHCPv6 Protocol instance
+ /// automatically.
+ ///
+ EFI_DHCP6_PACKET_OPTION **OptionList;
+ ///
+ /// The descriptor for the IA of the EFI DHCPv6 Protocol instance.
+ ///
+ EFI_DHCP6_IA_DESCRIPTOR IaDescriptor;
+ ///
+ /// If not NULL, the event will be signaled when any IPv6 address information of the
+ /// configured IA is updated, including IPv6 address, preferred lifetime and valid
+ /// lifetime, or the DHCPv6 S.A.R.R process fails. Otherwise, Start(),
+ /// renewrebind(), decline(), release() and stop() will be blocking
+ /// operations, and they will wait for the exchange process completion or failure.
+ ///
+ EFI_EVENT IaInfoEvent;
+ ///
+ /// If TRUE, the EFI DHCPv6 Protocol instance is willing to accept Reconfigure packet.
+ /// Otherwise, it will ignore it. Reconfigure Accept option can not be specified through
+ /// OptionList parameter.
+ ///
+ BOOLEAN ReconfigureAccept;
+ ///
+ /// If TRUE, the EFI DHCPv6 Protocol instance will send Solicit packet with Rapid
+ /// Commit option. Otherwise, Rapid Commit option will not be included in Solicit
+ /// packet. Rapid Commit option can not be specified through OptionList parameter.
+ ///
+ BOOLEAN RapidCommit;
+ ///
+ /// Parameter to control Solicit packet retransmission behavior. The
+ /// buffer can be freed after EFI_DHCP6_PROTOCOL.Configure() returns.
+ ///
+ EFI_DHCP6_RETRANSMISSION *SolicitRetransmission;
+} EFI_DHCP6_CONFIG_DATA;
+
+/**
+ EFI_DHCP6_INFO_CALLBACK is provided by the consumer of the EFI DHCPv6 Protocol
+ instance to intercept events that occurs in the DHCPv6 Information Request exchange process.
+
+ @param[in] This Pointer to the EFI_DHCP6_PROTOCOL instance that is used to configure this
+ callback function.
+ @param[in] Context Pointer to the context that is initialized in the EFI_DHCP6_PROTOCOL.InfoRequest().
+ @param[in] Packet Pointer to Reply packet that has been received. The EFI DHCPv6 Protocol instance is
+ responsible for freeing the buffer.
+
+ @retval EFI_SUCCESS Tell the EFI DHCPv6 Protocol instance to finish Information Request exchange process.
+ @retval EFI_NOT_READY Tell the EFI DHCPv6 Protocol instance to continue Information Request exchange process.
+ @retval EFI_ABORTED Tell the EFI DHCPv6 Protocol instance to abort the Information Request exchange process.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DHCP6_INFO_CALLBACK)(
+ IN EFI_DHCP6_PROTOCOL *This,
+ IN VOID *Context,
+ IN EFI_DHCP6_PACKET *Packet
+ );
+
+/**
+ Retrieve the current operating mode data and configuration data for the EFI DHCPv6 Protocol instance.
+
+ @param[in] This Pointer to the EFI_DHCP6_PROTOCOL instance.
+ @param[out] Dhcp6ModeData Pointer to the DHCPv6 mode data structure. The caller is responsible for freeing this
+ structure and each reference buffer.
+ @param[out] Dhcp6ConfigData Pointer to the DHCPv6 configuration data structure. The caller is responsible for
+ freeing this structure and each reference buffer.
+
+ @retval EFI_SUCCESS The mode data was returned.
+ @retval EFI_ACCESS_DENIED The EFI DHCPv6 Protocol instance has not been configured when Dhcp6ConfigData is not NULL.
+ @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE:
+ - This is NULL.
+ - Both Dhcp6ConfigData and Dhcp6ModeData are NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DHCP6_GET_MODE_DATA)(
+ IN EFI_DHCP6_PROTOCOL *This,
+ OUT EFI_DHCP6_MODE_DATA *Dhcp6ModeData OPTIONAL,
+ OUT EFI_DHCP6_CONFIG_DATA *Dhcp6ConfigData OPTIONAL
+ );
+
+/**
+ Initialize or clean up the configuration data for the EFI DHCPv6 Protocol instance.
+
+ The Configure() function is used to initialize or clean up the configuration data of the EFI
+ DHCPv6 Protocol instance.
+ - When Dhcp6CfgData is not NULL and Configure() is called successfully, the
+ configuration data will be initialized in the EFI DHCPv6 Protocol instance and the state of the
+ configured IA will be transferred into Dhcp6Init.
+ - When Dhcp6CfgData is NULL and Configure() is called successfully, the configuration
+ data will be cleaned up and no IA will be associated with the EFI DHCPv6 Protocol instance.
+
+ To update the configuration data for an EFI DCHPv6 Protocol instance, the original data must be
+ cleaned up before setting the new configuration data.
+
+ @param[in] This Pointer to the EFI_DHCP6_PROTOCOL instance.
+ @param[in] Dhcp6CfgData Pointer to the DHCPv6 configuration data structure.
+
+ @retval EFI_SUCCESS The mode data was returned.
+ @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE
+ - This is NULL.
+ - OptionCount > 0 and OptionList is NULL.
+ - OptionList is not NULL, and Client Id option, Reconfigure Accept option,
+ Rapid Commit option or any IA option is specified in the OptionList.
+ - IaDescriptor.Type is neither EFI_DHCP6_IA_TYPE_NA nor EFI_DHCP6_IA_TYPE_NA.
+ - IaDescriptor is not unique.
+ - Both IaInfoEvent and SolicitRetransimssion are NULL.
+ - SolicitRetransmission is not NULL, and both SolicitRetransimssion->Mrc and
+ SolicitRetransmission->Mrd are zero.
+ @retval EFI_ACCESS_DENIED The EFI DHCPv6 Protocol instance has been already configured
+ when Dhcp6CfgData is not NULL.
+ The EFI DHCPv6 Protocol instance has already started the
+ DHCPv6 S.A.R.R when Dhcp6CfgData is NULL.
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DHCP6_CONFIGURE)(
+ IN EFI_DHCP6_PROTOCOL *This,
+ IN EFI_DHCP6_CONFIG_DATA *Dhcp6CfgData OPTIONAL
+ );
+
+/**
+ Start the DHCPv6 S.A.R.R process.
+
+ The Start() function starts the DHCPv6 S.A.R.R process. This function can be called only when
+ the state of the configured IA is in the Dhcp6Init state. If the DHCPv6 S.A.R.R process completes
+ successfully, the state of the configured IA will be transferred through Dhcp6Selecting and
+ Dhcp6Requesting to Dhcp6Bound state. The update of the IPv6 addresses will be notified through
+ EFI_DHCP6_CONFIG_DATA.IaInfoEvent. At the time when each event occurs in this process, the
+ callback function set by EFI_DHCP6_PROTOCOL.Configure() will be called and the user can take
+ this opportunity to control the process. If EFI_DHCP6_CONFIG_DATA.IaInfoEvent is NULL, the
+ Start() function call is a blocking operation. It will return after the DHCPv6 S.A.R.R process
+ completes or aborted by users. If the process is aborted by system or network error, the state of
+ the configured IA will be transferred to Dhcp6Init. The Start() function can be called again to
+ restart the process.
+
+ @param[in] This Pointer to the EFI_DHCP6_PROTOCOL instance.
+
+ @retval EFI_SUCCESS The DHCPv6 S.A.R.R process is completed and at least one IPv6
+ address has been bound to the configured IA when
+ EFI_DHCP6_CONFIG_DATA.IaInfoEvent is NULL.
+ The DHCPv6 S.A.R.R process is started when
+ EFI_DHCP6_CONFIG_DATA.IaInfoEvent is not NULL.
+ @retval EFI_ACCESS_DENIED The EFI DHCPv6 Child instance hasn't been configured.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+ @retval EFI_ALREADY_STARTED The DHCPv6 S.A.R.R process has already started.
+ @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
+ @retval EFI_NO_RESPONSE The DHCPv6 S.A.R.R process failed because of no response.
+ @retval EFI_NO_MAPPING No IPv6 address has been bound to the configured IA after the
+ DHCPv6 S.A.R.R process.
+ @retval EFI_ABORTED The DHCPv6 S.A.R.R process aborted by user.
+ @retval EFI_NO_MEDIA There was a media error.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DHCP6_START)(
+ IN EFI_DHCP6_PROTOCOL *This
+ );
+
+/**
+ Request configuration information without the assignment of any IA addresses of the client.
+
+ The InfoRequest() function is used to request configuration information without the assignment
+ of any IPv6 address of the client. Client sends out Information Request packet to obtain
+ the required configuration information, and DHCPv6 server responds with Reply packet containing
+ the information for the client. The received Reply packet will be passed to the user by
+ ReplyCallback function. If user returns EFI_NOT_READY from ReplyCallback, the EFI DHCPv6
+ Protocol instance will continue to receive other Reply packets unless timeout according to
+ the Retransmission parameter. Otherwise, the Information Request exchange process will be
+ finished successfully if user returns EFI_SUCCESS from ReplyCallback.
+
+ @param[in] This Pointer to the EFI_DHCP6_PROTOCOL instance.
+ @param[in] SendClientId If TRUE, the EFI DHCPv6 Protocol instance will build Client
+ Identifier option and include it into Information Request
+ packet. If FALSE, Client Identifier option will not be included.
+ Client Identifier option can not be specified through OptionList
+ parameter.
+ @param[in] OptionRequest Pointer to the Option Request option in the Information Request
+ packet. Option Request option can not be specified through
+ OptionList parameter.
+ @param[in] OptionCount Number of options in OptionList.
+ @param[in] OptionList List of other DHCPv6 options. These options will be appended
+ to the Option Request option. The caller is responsible for
+ freeing this buffer. Type is defined in EFI_DHCP6_PROTOCOL.GetModeData().
+ @param[in] Retransmission Parameter to control Information Request packet retransmission
+ behavior. The buffer can be freed after EFI_DHCP6_PROTOCOL.InfoRequest()
+ returns.
+ @param[in] TimeoutEvent If not NULL, this event is signaled when the information request
+ exchange aborted because of no response. If NULL, the function
+ call is a blocking operation; and it will return after the
+ information-request exchange process finish or aborted by users.
+ @param[in] ReplyCallback The callback function is to intercept various events that occur
+ in the Information Request exchange process. It should not be
+ set to NULL.
+ @param[in] CallbackContext Pointer to the context that will be passed to ReplyCallback.
+
+ @retval EFI_SUCCESS The DHCPv6 S.A.R.R process is completed and at least one IPv6
+ @retval EFI_SUCCESS The DHCPv6 information request exchange process completed
+ when TimeoutEvent is NULL. Information Request packet has been
+ sent to DHCPv6 server when TimeoutEvent is not NULL.
+ @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE:
+ - This is NULL.
+ - OptionRequest is NULL or OptionRequest->OpCode is invalid.
+ - OptionCount > 0 and OptionList is NULL.
+ - OptionList is not NULL, and Client Identify option or
+ Option Request option is specified in the OptionList.
+ - Retransimssion is NULL.
+ - Both Retransimssion->Mrc and Retransmission->Mrd are zero.
+ - ReplyCallback is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
+ @retval EFI_NO_RESPONSE The DHCPv6 information request exchange process failed
+ because of no response, or not all requested-options are
+ responded by DHCPv6 servers when Timeout happened.
+ @retval EFI_ABORTED The DHCPv6 information request exchange process aborted by user.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DHCP6_INFO_REQUEST)(
+ IN EFI_DHCP6_PROTOCOL *This,
+ IN BOOLEAN SendClientId,
+ IN EFI_DHCP6_PACKET_OPTION *OptionRequest,
+ IN UINT32 OptionCount,
+ IN EFI_DHCP6_PACKET_OPTION *OptionList[] OPTIONAL,
+ IN EFI_DHCP6_RETRANSMISSION *Retransmission,
+ IN EFI_EVENT TimeoutEvent OPTIONAL,
+ IN EFI_DHCP6_INFO_CALLBACK ReplyCallback,
+ IN VOID *CallbackContext OPTIONAL
+ );
+
+/**
+ Manually extend the valid and preferred lifetimes for the IPv6 addresses of the configured
+ IA and update other configuration parameters by sending Renew or Rebind packet.
+
+ The RenewRebind() function is used to manually extend the valid and preferred lifetimes for the
+ IPv6 addresses of the configured IA and update other configuration parameters by sending Renew or
+ Rebind packet.
+ - When RebindRequest is FALSE and the state of the configured IA is Dhcp6Bound, it
+ will send Renew packet to the previously DHCPv6 server and transfer the state of the configured
+ IA to Dhcp6Renewing. If valid Reply packet received, the state transfers to Dhcp6Bound
+ and the valid and preferred timer restarts. If fails, the state transfers to Dhcp6Bound but the
+ timer continues.
+ - When RebindRequest is TRUE and the state of the configured IA is Dhcp6Bound, it will
+ send Rebind packet. If valid Reply packet received, the state transfers to Dhcp6Bound and the
+ valid and preferred timer restarts. If fails, the state transfers to Dhcp6Init and the IA can't
+ be used.
+
+ @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
+ @param[in] RebindRequest If TRUE, it will send Rebind packet and enter the Dhcp6Rebinding state.
+ Otherwise, it will send Renew packet and enter the Dhcp6Renewing state.
+
+ @retval EFI_SUCCESS The DHCPv6 renew/rebind exchange process has completed and at
+ least one IPv6 address of the configured IA has been bound again
+ when EFI_DHCP6_CONFIG_DATA.IaInfoEvent is NULL.
+ The EFI DHCPv6 Protocol instance has sent Renew or Rebind packet
+ when EFI_DHCP6_CONFIG_DATA.IaInfoEvent is not NULL.
+ @retval EFI_ACCESS_DENIED The EFI DHCPv6 Child instance hasn't been configured, or the state
+ of the configured IA is not in Dhcp6Bound.
+ @retval EFI_ALREADY_STARTED The state of the configured IA has already entered Dhcp6Renewing
+ when RebindRequest is FALSE.
+ The state of the configured IA has already entered Dhcp6Rebinding
+ when RebindRequest is TRUE.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or system error occurred.
+ @retval EFI_NO_RESPONSE The DHCPv6 renew/rebind exchange process failed because of no response.
+ @retval EFI_NO_MAPPING No IPv6 address has been bound to the configured IA after the DHCPv6
+ renew/rebind exchange process.
+ @retval EFI_ABORTED The DHCPv6 renew/rebind exchange process aborted by user.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DHCP6_RENEW_REBIND)(
+ IN EFI_DHCP6_PROTOCOL *This,
+ IN BOOLEAN RebindRequest
+ );
+
+/**
+ Inform that one or more IPv6 addresses assigned by a server are already in use by
+ another node.
+
+ The Decline() function is used to manually decline the assignment of IPv6 addresses, which
+ have been already used by another node. If all IPv6 addresses of the configured IA are declined
+ through this function, the state of the IA will switch through Dhcp6Declining to Dhcp6Init,
+ otherwise, the state of the IA will restore to Dhcp6Bound after the declining process. The
+ Decline() can only be called when the IA is in Dhcp6Bound state. If the
+ EFI_DHCP6_CONFIG_DATA.IaInfoEvent is NULL, this function is a blocking operation. It
+ will return after the declining process finishes, or aborted by user.
+
+ @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
+ @param[in] AddressCount Number of declining IPv6 addresses.
+ @param[in] Addresses Pointer to the buffer stored all the declining IPv6 addresses.
+
+ @retval EFI_SUCCESS The DHCPv6 decline exchange process has completed when
+ EFI_DHCP6_CONFIG_DATA.IaInfoEvent is NULL.
+ The EFI DHCPv6 Protocol instance has sent Decline packet when
+ EFI_DHCP6_CONFIG_DATA.IaInfoEvent is not NULL.
+ @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE
+ - This is NULL.
+ - AddressCount is zero or Addresses is NULL.
+ @retval EFI_NOT_FOUND Any specified IPv6 address is not correlated with the configured IA
+ for this instance.
+ @retval EFI_ACCESS_DENIED The EFI DHCPv6 Child instance hasn't been configured, or the
+ state of the configured IA is not in Dhcp6Bound.
+ @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
+ @retval EFI_ABORTED The DHCPv6 decline exchange process aborted by user.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DHCP6_DECLINE)(
+ IN EFI_DHCP6_PROTOCOL *This,
+ IN UINT32 AddressCount,
+ IN EFI_IPv6_ADDRESS *Addresses
+ );
+
+/**
+ Release one or more IPv6 addresses associated with the configured IA for current instance.
+
+ The Release() function is used to manually release the one or more IPv6 address. If AddressCount
+ is zero, it will release all IPv6 addresses of the configured IA. If all IPv6 addresses of the IA
+ are released through this function, the state of the IA will switch through Dhcp6Releasing to
+ Dhcp6Init, otherwise, the state of the IA will restore to Dhcp6Bound after the releasing process.
+ The Release() can only be called when the IA is in Dhcp6Bound state. If the
+ EFI_DHCP6_CONFIG_DATA.IaInfoEvent is NULL, the function is a blocking operation. It will return
+ after the releasing process finishes, or aborted by user.
+
+ @param[in] This Pointer to the EFI_DHCP6_PROTOCOL instance.
+ @param[in] AddressCount Number of releasing IPv6 addresses.
+ @param[in] Addresses Pointer to the buffer stored all the releasing IPv6 addresses.
+ Ignored if AddressCount is zero.
+ @retval EFI_SUCCESS The DHCPv6 release exchange process has completed when
+ EFI_DHCP6_CONFIG_DATA.IaInfoEvent is NULL.
+ The EFI DHCPv6 Protocol instance has sent Release packet when
+ EFI_DHCP6_CONFIG_DATA.IaInfoEvent is not NULL.
+ @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE
+ - This is NULL.
+ - AddressCount is not zero or Addresses is NULL.
+ @retval EFI_NOT_FOUND Any specified IPv6 address is not correlated with the configured
+ IA for this instance.
+ @retval EFI_ACCESS_DENIED The EFI DHCPv6 Child instance hasn't been configured, or the
+ state of the configured IA is not in Dhcp6Bound.
+ @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
+ @retval EFI_ABORTED The DHCPv6 release exchange process aborted by user.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DHCP6_RELEASE)(
+ IN EFI_DHCP6_PROTOCOL *This,
+ IN UINT32 AddressCount,
+ IN EFI_IPv6_ADDRESS *Addresses
+ );
+
+/**
+ Stop the DHCPv6 S.A.R.R process.
+
+ The Stop() function is used to stop the DHCPv6 S.A.R.R process. If this function is called
+ successfully, all the IPv6 addresses of the configured IA will be released and the state of
+ the configured IA will be transferred to Dhcp6Init.
+
+ @param[in] This Pointer to the EFI_DHCP6_PROTOCOL instance.
+
+ @retval EFI_SUCCESS The DHCPv6 S.A.R.R process has been stopped when
+ EFI_DHCP6_CONFIG_DATA.IaInfoEvent is NULL.
+ The EFI DHCPv6 Protocol instance has sent Release packet if
+ need release or has been stopped if needn't, when
+ EFI_DHCP6_CONFIG_DATA.IaInfoEvent is not NULL.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DHCP6_STOP)(
+ IN EFI_DHCP6_PROTOCOL *This
+ );
+
+/**
+ Parse the option data in the DHCPv6 packet.
+
+ The Parse() function is used to retrieve the option list in the DHCPv6 packet.
+
+ @param[in] This Pointer to the EFI_DHCP6_PROTOCOL instance.
+
+ @param[in] Packet Pointer to packet to be parsed.
+ @param[in] OptionCount On input, the number of entries in the PacketOptionList.
+ On output, the number of DHCPv6 options in the Packet.
+ @param[in] PacketOptionList List of pointers to the DHCPv6 options in the Packet.
+ The OpCode and OpLen in EFI_DHCP6_PACKET_OPTION are
+ both stored in network byte order.
+ @retval EFI_SUCCESS The packet was successfully parsed.
+ @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE
+ - This is NULL.
+ - Packet is NULL.
+ - Packet is not a well-formed DHCPv6 packet.
+ - OptionCount is NULL.
+ - *OptionCount is not zero and PacketOptionList is NULL.
+ @retval EFI_BUFFER_TOO_SMALL *OptionCount is smaller than the number of options that were
+ found in the Packet.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DHCP6_PARSE)(
+ IN EFI_DHCP6_PROTOCOL *This,
+ IN EFI_DHCP6_PACKET *Packet,
+ IN OUT UINT32 *OptionCount,
+ OUT EFI_DHCP6_PACKET_OPTION *PacketOptionList[] OPTIONAL
+ );
+
+///
+/// The EFI DHCPv6 Protocol is used to get IPv6 addresses and other configuration parameters
+/// from DHCPv6 servers.
+///
+struct _EFI_DHCP6_PROTOCOL {
+ EFI_DHCP6_GET_MODE_DATA GetModeData;
+ EFI_DHCP6_CONFIGURE Configure;
+ EFI_DHCP6_START Start;
+ EFI_DHCP6_INFO_REQUEST InfoRequest;
+ EFI_DHCP6_RENEW_REBIND RenewRebind;
+ EFI_DHCP6_DECLINE Decline;
+ EFI_DHCP6_RELEASE Release;
+ EFI_DHCP6_STOP Stop;
+ EFI_DHCP6_PARSE Parse;
+};
+
+extern EFI_GUID gEfiDhcp6ProtocolGuid;
+extern EFI_GUID gEfiDhcp6ServiceBindingProtocolGuid;
+
+#endif
diff --git a/src/include/ipxe/efi/Protocol/Dns4.h b/src/include/ipxe/efi/Protocol/Dns4.h
new file mode 100644
index 00000000..0ab07e51
--- /dev/null
+++ b/src/include/ipxe/efi/Protocol/Dns4.h
@@ -0,0 +1,538 @@
+/** @file
+ This file defines the EFI Domain Name Service Binding Protocol interface. It is split
+ into the following two main sections:
+ DNSv4 Service Binding Protocol (DNSv4SB)
+ DNSv4 Protocol (DNSv4)
+
+ Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Revision Reference:
+ This Protocol is introduced in UEFI Specification 2.5
+
+**/
+
+#ifndef __EFI_DNS4_PROTOCOL_H__
+#define __EFI_DNS4_PROTOCOL_H__
+
+FILE_LICENCE ( BSD2_PATENT );
+
+#define EFI_DNS4_SERVICE_BINDING_PROTOCOL_GUID \
+ { \
+ 0xb625b186, 0xe063, 0x44f7, {0x89, 0x5, 0x6a, 0x74, 0xdc, 0x6f, 0x52, 0xb4 } \
+ }
+
+#define EFI_DNS4_PROTOCOL_GUID \
+ { \
+ 0xae3d28cc, 0xe05b, 0x4fa1, {0xa0, 0x11, 0x7e, 0xb5, 0x5a, 0x3f, 0x14, 0x1 } \
+ }
+
+typedef struct _EFI_DNS4_PROTOCOL EFI_DNS4_PROTOCOL;
+
+///
+/// EFI_DNS4_CONFIG_DATA
+///
+typedef struct {
+ ///
+ /// Count of the DNS servers. When used with GetModeData(),
+ /// this field is the count of originally configured servers when
+ /// Configure() was called for this instance. When used with
+ /// Configure() this is the count of caller-supplied servers. If the
+ /// DnsServerListCount is zero, the DNS server configuration
+ /// will be retrieved from DHCP server automatically.
+ ///
+ UINTN DnsServerListCount;
+ ///
+ /// Pointer to DNS server list containing DnsServerListCount entries or NULL
+ /// if DnsServerListCountis 0. For Configure(), this will be NULL when there are
+ /// no caller supplied server addresses, and, the DNS instance will retrieve
+ /// DNS server from DHCP Server. The provided DNS server list is
+ /// recommended to be filled up in the sequence of preference. When
+ /// used with GetModeData(), the buffer containing the list will
+ /// be allocated by the driver implementing this protocol and must be
+ /// freed by the caller. When used with Configure(), the buffer
+ /// containing the list will be allocated and released by the caller.
+ ///
+ EFI_IPv4_ADDRESS *DnsServerList;
+ ///
+ /// Set to TRUE to use the default IP address/subnet mask and default routing table.
+ ///
+ BOOLEAN UseDefaultSetting;
+ ///
+ /// If TRUE, enable DNS cache function for this DNS instance. If FALSE, all DNS
+ /// query will not lookup local DNS cache.
+ ///
+ BOOLEAN EnableDnsCache;
+ ///
+ /// Use the protocol number defined in "Links to UEFI-Related
+ /// Documents"(http://uefi.org/uefi) under the heading "IANA
+ /// Protocol Numbers". Only TCP or UDP are supported, and other
+ /// protocol values are invalid. An implementation can choose to
+ /// support only UDP, or both TCP and UDP.
+ ///
+ UINT8 Protocol;
+ ///
+ /// If UseDefaultSetting is FALSE indicates the station address to use.
+ ///
+ EFI_IPv4_ADDRESS StationIp;
+ ///
+ /// If UseDefaultSetting is FALSE indicates the subnet mask to use.
+ ///
+ EFI_IPv4_ADDRESS SubnetMask;
+ ///
+ /// Local port number. Set to zero to use the automatically assigned port number.
+ ///
+ UINT16 LocalPort;
+ ///
+ /// Retry number if no response received after RetryInterval.
+ ///
+ UINT32 RetryCount;
+ ///
+ /// Minimum interval of retry is 2 second. If the retry interval is less than 2
+ /// seconds, then use the 2 seconds.
+ ///
+ UINT32 RetryInterval;
+} EFI_DNS4_CONFIG_DATA;
+
+///
+/// EFI_DNS4_CACHE_ENTRY
+///
+typedef struct {
+ ///
+ /// Host name.
+ ///
+ CHAR16 *HostName;
+ ///
+ /// IP address of this host.
+ ///
+ EFI_IPv4_ADDRESS *IpAddress;
+ ///
+ /// Time in second unit that this entry will remain in DNS cache. A value of zero
+ /// means that this entry is permanent. A nonzero value will override the existing
+ /// one if this entry to be added is dynamic entry. Implementations may set its
+ /// default timeout value for the dynamically created DNS cache entry after one DNS
+ /// resolve succeeds.
+ ///
+ UINT32 Timeout;
+} EFI_DNS4_CACHE_ENTRY;
+
+///
+/// EFI_DNS4_MODE_DATA
+///
+typedef struct {
+ ///
+ /// The configuration data of this instance.
+ ///
+ EFI_DNS4_CONFIG_DATA DnsConfigData;
+ ///
+ /// Number of configured DNS server. Each DNS instance has its own DNS server
+ /// configuration.
+ ///
+ UINT32 DnsServerCount;
+ ///
+ /// Pointer to common list of addresses of all configured DNS server
+ /// used by EFI_DNS4_PROTOCOL instances. List will include
+ /// DNS servers configured by this or any other EFI_DNS4_PROTOCOL instance.
+ /// The storage for this list is allocated by the driver publishing this
+ /// protocol, and must be freed by the caller.
+ ///
+ EFI_IPv4_ADDRESS *DnsServerList;
+ ///
+ /// Number of DNS Cache entries. The DNS Cache is shared among all DNS instances.
+ ///
+ UINT32 DnsCacheCount;
+ ///
+ /// Pointer to a buffer containing DnsCacheCount DNS Cache
+ /// entry structures. The storage for this list is allocated by the driver
+ /// publishing this protocol and must be freed by caller.
+ ///
+ EFI_DNS4_CACHE_ENTRY *DnsCacheList;
+} EFI_DNS4_MODE_DATA;
+
+///
+/// DNS_HOST_TO_ADDR_DATA
+///
+typedef struct {
+ ///
+ /// Number of the returned IP addresses.
+ ///
+ UINT32 IpCount;
+ ///
+ /// Pointer to the all the returned IP addresses.
+ ///
+ EFI_IPv4_ADDRESS *IpList;
+} DNS_HOST_TO_ADDR_DATA;
+
+///
+/// DNS_ADDR_TO_HOST_DATA
+///
+typedef struct {
+ ///
+ /// Pointer to the primary name for this host address. It's the caller's
+ /// responsibility to free the response memory.
+ ///
+ CHAR16 *HostName;
+} DNS_ADDR_TO_HOST_DATA;
+
+///
+/// DNS_RESOURCE_RECORD
+///
+typedef struct {
+ ///
+ /// The Owner name.
+ ///
+ CHAR8 *QName;
+ ///
+ /// The Type Code of this RR.
+ ///
+ UINT16 QType;
+ ///
+ /// The CLASS code of this RR.
+ ///
+ UINT16 QClass;
+ ///
+ /// 32 bit integer which specify the time interval that the resource record may be
+ /// cached before the source of the information should again be consulted. Zero means
+ /// this RR can not be cached.
+ ///
+ UINT32 TTL;
+ ///
+ /// 16 big integer which specify the length of RData.
+ ///
+ UINT16 DataLength;
+ ///
+ /// A string of octets that describe the resource, the format of this information
+ /// varies according to QType and QClass difference.
+ ///
+ CHAR8 *RData;
+} DNS_RESOURCE_RECORD;
+
+///
+/// DNS_GENERAL_LOOKUP_DATA
+///
+typedef struct {
+ ///
+ /// Number of returned matching RRs.
+ ///
+ UINTN RRCount;
+ ///
+ /// Pointer to the all the returned matching RRs. It's caller responsibility to free
+ /// the allocated memory to hold the returned RRs.
+ ///
+ DNS_RESOURCE_RECORD *RRList;
+} DNS_GENERAL_LOOKUP_DATA;
+
+///
+/// EFI_DNS4_COMPLETION_TOKEN
+///
+typedef struct {
+ ///
+ /// This Event will be signaled after the Status field is updated by the EFI DNS
+ /// protocol driver. The type of Event must be EFI_NOTIFY_SIGNAL.
+ ///
+ EFI_EVENT Event;
+ ///
+ /// Will be set to one of the following values:
+ /// EFI_SUCCESS: The host name to address translation completed successfully.
+ /// EFI_NOT_FOUND: No matching Resource Record (RR) is found.
+ /// EFI_TIMEOUT: No DNS server reachable, or RetryCount was exhausted without
+ /// response from all specified DNS servers.
+ /// EFI_DEVICE_ERROR: An unexpected system or network error occurred.
+ /// EFI_NO_MEDIA: There was a media error.
+ ///
+ EFI_STATUS Status;
+ ///
+ /// Retry number if no response received after RetryInterval. If zero, use the
+ /// parameter configured through Dns.Configure() interface.
+ ///
+ UINT32 RetryCount;
+ ///
+ /// Minimum interval of retry is 2 second. If the retry interval is less than 2
+ /// seconds, then use the 2 seconds. If zero, use the parameter configured through
+ /// Dns.Configure() interface.
+ UINT32 RetryInterval;
+ ///
+ /// DNSv4 completion token data
+ ///
+ union {
+ ///
+ /// When the Token is used for host name to address translation, H2AData is a pointer
+ /// to the DNS_HOST_TO_ADDR_DATA.
+ ///
+ DNS_HOST_TO_ADDR_DATA *H2AData;
+ ///
+ /// When the Token is used for host address to host name translation, A2HData is a
+ /// pointer to the DNS_ADDR_TO_HOST_DATA.
+ ///
+ DNS_ADDR_TO_HOST_DATA *A2HData;
+ ///
+ /// When the Token is used for a general lookup function, GLookupDATA is a pointer to
+ /// the DNS_GENERAL_LOOKUP_DATA.
+ ///
+ DNS_GENERAL_LOOKUP_DATA *GLookupData;
+ } RspData;
+} EFI_DNS4_COMPLETION_TOKEN;
+
+/**
+ Retrieve mode data of this DNS instance.
+
+ This function is used to retrieve DNS mode data for this DNS instance.
+
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.
+ @param[out] DnsModeData Point to the mode data.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_NOT_STARTED When DnsConfigData is queried, no configuration data
+ is available because this instance has not been
+ configured.
+ @retval EFI_INVALID_PARAMETER This is NULL or DnsModeData is NULL.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DNS4_GET_MODE_DATA)(
+ IN EFI_DNS4_PROTOCOL *This,
+ OUT EFI_DNS4_MODE_DATA *DnsModeData
+ );
+
+/**
+ Configure this DNS instance.
+
+ This function is used to configure DNS mode data for this DNS instance.
+
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.
+ @param[in] DnsConfigData Point to the Configuration data.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_UNSUPPORTED The designated protocol is not supported.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ The StationIp address provided in DnsConfigData is not a
+ valid unicast.
+ DnsServerList is NULL while DnsServerListCount
+ is not ZERO.
+ DnsServerListCount is ZERO while DnsServerList
+ is not NULL
+ @retval EFI_OUT_OF_RESOURCES The DNS instance data or required space could not be
+ allocated.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The
+ EFI DNSv4 Protocol instance is not configured.
+ @retval EFI_ALREADY_STARTED Second call to Configure() with DnsConfigData. To
+ reconfigure the instance the caller must call Configure()
+ with NULL first to return driver to unconfigured state.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DNS4_CONFIGURE)(
+ IN EFI_DNS4_PROTOCOL *This,
+ IN EFI_DNS4_CONFIG_DATA *DnsConfigData
+ );
+
+/**
+ Host name to host address translation.
+
+ The HostNameToIp () function is used to translate the host name to host IP address. A
+ type A query is used to get the one or more IP addresses for this host.
+
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.
+ @param[in] HostName Host name.
+ @param[in] Token Point to the completion token to translate host name
+ to host address.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ Token is NULL.
+ Token.Event is NULL.
+ HostName is NULL. HostName string is unsupported format.
+ @retval EFI_NO_MAPPING There's no source address is available for use.
+ @retval EFI_NOT_STARTED This instance has not been started.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DNS4_HOST_NAME_TO_IP)(
+ IN EFI_DNS4_PROTOCOL *This,
+ IN CHAR16 *HostName,
+ IN EFI_DNS4_COMPLETION_TOKEN *Token
+ );
+
+/**
+ IPv4 address to host name translation also known as Reverse DNS lookup.
+
+ The IpToHostName() function is used to translate the host address to host name. A type PTR
+ query is used to get the primary name of the host. Support of this function is optional.
+
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.
+ @param[in] IpAddress Ip Address.
+ @param[in] Token Point to the completion token to translate host
+ address to host name.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_UNSUPPORTED This function is not supported.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ Token is NULL.
+ Token.Event is NULL.
+ IpAddress is not valid IP address .
+ @retval EFI_NO_MAPPING There's no source address is available for use.
+ @retval EFI_ALREADY_STARTED This Token is being used in another DNS session.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DNS4_IP_TO_HOST_NAME)(
+ IN EFI_DNS4_PROTOCOL *This,
+ IN EFI_IPv4_ADDRESS IpAddress,
+ IN EFI_DNS4_COMPLETION_TOKEN *Token
+ );
+
+/**
+ Retrieve arbitrary information from the DNS server.
+
+ This GeneralLookup() function retrieves arbitrary information from the DNS. The caller
+ supplies a QNAME, QTYPE, and QCLASS, and all of the matching RRs are returned. All
+ RR content (e.g., TTL) was returned. The caller need parse the returned RR to get
+ required information. The function is optional.
+
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.
+ @param[in] QName Pointer to Query Name.
+ @param[in] QType Query Type.
+ @param[in] QClass Query Name.
+ @param[in] Token Point to the completion token to retrieve arbitrary
+ information.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_UNSUPPORTED This function is not supported. Or the requested
+ QType is not supported
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ Token is NULL.
+ Token.Event is NULL.
+ QName is NULL.
+ @retval EFI_NO_MAPPING There's no source address is available for use.
+ @retval EFI_ALREADY_STARTED This Token is being used in another DNS session.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DNS4_GENERAL_LOOKUP)(
+ IN EFI_DNS4_PROTOCOL *This,
+ IN CHAR8 *QName,
+ IN UINT16 QType,
+ IN UINT16 QClass,
+ IN EFI_DNS4_COMPLETION_TOKEN *Token
+ );
+
+/**
+ This function is to update the DNS Cache.
+
+ The UpdateDnsCache() function is used to add/delete/modify DNS cache entry. DNS cache
+ can be normally dynamically updated after the DNS resolve succeeds. This function
+ provided capability to manually add/delete/modify the DNS cache.
+
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.
+ @param[in] DeleteFlag If FALSE, this function is to add one entry to the
+ DNS Cahce. If TRUE, this function will delete
+ matching DNS Cache entry.
+ @param[in] Override If TRUE, the maching DNS cache entry will be
+ overwritten with the supplied parameter. If FALSE,
+ EFI_ACCESS_DENIED will be returned if the entry to
+ be added is already existed.
+ @param[in] DnsCacheEntry Pointer to DNS Cache entry.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ DnsCacheEntry.HostName is NULL.
+ DnsCacheEntry.IpAddress is NULL.
+ DnsCacheEntry.Timeout is zero.
+ @retval EFI_ACCESS_DENIED The DNS cache entry already exists and Override is
+ not TRUE.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DNS4_UPDATE_DNS_CACHE)(
+ IN EFI_DNS4_PROTOCOL *This,
+ IN BOOLEAN DeleteFlag,
+ IN BOOLEAN Override,
+ IN EFI_DNS4_CACHE_ENTRY DnsCacheEntry
+ );
+
+/**
+ Polls for incoming data packets and processes outgoing data packets.
+
+ The Poll() function can be used by network drivers and applications to increase the
+ rate that data packets are moved between the communications device and the transmit
+ and receive queues.
+ In some systems, the periodic timer event in the managed network driver may not poll
+ the underlying communications device fast enough to transmit and/or receive all data
+ packets without missing incoming packets or dropping outgoing packets. Drivers and
+ applications that are experiencing packet loss should try calling the Poll()
+ function more often.
+
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Incoming or outgoing data was processed.
+ @retval EFI_NOT_STARTED This EFI DNS Protocol instance has not been started.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive
+ queue. Consider increasing the polling rate.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DNS4_POLL)(
+ IN EFI_DNS4_PROTOCOL *This
+ );
+
+/**
+ Abort an asynchronous DNS operation, including translation between IP and Host, and
+ general look up behavior.
+
+ The Cancel() function is used to abort a pending resolution request. After calling
+ this function, Token.Status will be set to EFI_ABORTED and then Token.Event will be
+ signaled. If the token is not in one of the queues, which usually means that the
+ asynchronous operation has completed, this function will not signal the token and
+ EFI_NOT_FOUND is returned.
+
+ @param[in] This Pointer to EFI_DNS4_PROTOCOL instance.
+ @param[in] Token Pointer to a token that has been issued by
+ EFI_DNS4_PROTOCOL.HostNameToIp (),
+ EFI_DNS4_PROTOCOL.IpToHostName() or
+ EFI_DNS4_PROTOCOL.GeneralLookup().
+ If NULL, all pending tokens are aborted.
+
+ @retval EFI_SUCCESS Incoming or outgoing data was processed.
+ @retval EFI_NOT_STARTED This EFI DNS4 Protocol instance has not been started.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_NOT_FOUND When Token is not NULL, and the asynchronous DNS
+ operation was not found in the transmit queue. It
+ was either completed or was not issued by
+ HostNameToIp(), IpToHostName() or GeneralLookup().
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DNS4_CANCEL)(
+ IN EFI_DNS4_PROTOCOL *This,
+ IN EFI_DNS4_COMPLETION_TOKEN *Token
+ );
+
+///
+/// The EFI_DNS4_Protocol provides the function to get the host name and address
+/// mapping, also provides pass through interface to retrieve arbitrary information
+/// from DNS.
+///
+struct _EFI_DNS4_PROTOCOL {
+ EFI_DNS4_GET_MODE_DATA GetModeData;
+ EFI_DNS4_CONFIGURE Configure;
+ EFI_DNS4_HOST_NAME_TO_IP HostNameToIp;
+ EFI_DNS4_IP_TO_HOST_NAME IpToHostName;
+ EFI_DNS4_GENERAL_LOOKUP GeneralLookUp;
+ EFI_DNS4_UPDATE_DNS_CACHE UpdateDnsCache;
+ EFI_DNS4_POLL Poll;
+ EFI_DNS4_CANCEL Cancel;
+};
+
+extern EFI_GUID gEfiDns4ServiceBindingProtocolGuid;
+extern EFI_GUID gEfiDns4ProtocolGuid;
+
+#endif
diff --git a/src/include/ipxe/efi/Protocol/Dns6.h b/src/include/ipxe/efi/Protocol/Dns6.h
new file mode 100644
index 00000000..3b88c88e
--- /dev/null
+++ b/src/include/ipxe/efi/Protocol/Dns6.h
@@ -0,0 +1,535 @@
+/** @file
+ This file defines the EFI DNSv6 (Domain Name Service version 6) Protocol. It is split
+ into the following two main sections:
+ DNSv6 Service Binding Protocol (DNSv6SB)
+ DNSv6 Protocol (DNSv6)
+
+ Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Revision Reference:
+ This Protocol is introduced in UEFI Specification 2.5
+
+**/
+
+#ifndef __EFI_DNS6_PROTOCOL_H__
+#define __EFI_DNS6_PROTOCOL_H__
+
+FILE_LICENCE ( BSD2_PATENT );
+
+#define EFI_DNS6_SERVICE_BINDING_PROTOCOL_GUID \
+ { \
+ 0x7f1647c8, 0xb76e, 0x44b2, {0xa5, 0x65, 0xf7, 0xf, 0xf1, 0x9c, 0xd1, 0x9e } \
+ }
+
+#define EFI_DNS6_PROTOCOL_GUID \
+ { \
+ 0xca37bc1f, 0xa327, 0x4ae9, {0x82, 0x8a, 0x8c, 0x40, 0xd8, 0x50, 0x6a, 0x17 } \
+ }
+
+typedef struct _EFI_DNS6_PROTOCOL EFI_DNS6_PROTOCOL;
+
+///
+/// EFI_DNS6_CONFIG_DATA
+///
+typedef struct {
+ ///
+ /// If TRUE, enable DNS cache function for this DNS instance. If FALSE, all DNS query
+ /// will not lookup local DNS cache.
+ ///
+ BOOLEAN EnableDnsCache;
+ ///
+ /// Use the protocol number defined in
+ /// http://www.iana.org/assignments/protocol-numbers. Beside TCP/UDP, Other protocol
+ /// is invalid value. An implementation can choose to support UDP, or both TCP and UDP.
+ ///
+ UINT8 Protocol;
+ ///
+ /// The local IP address to use. Set to zero to let the underlying IPv6
+ /// driver choose a source address. If not zero it must be one of the
+ /// configured IP addresses in the underlying IPv6 driver.
+ ///
+ EFI_IPv6_ADDRESS StationIp;
+ ///
+ /// Local port number. Set to zero to use the automatically assigned port number.
+ ///
+ UINT16 LocalPort;
+ ///
+ /// Count of the DNS servers. When used with GetModeData(),
+ /// this field is the count of originally configured servers when
+ /// Configure() was called for this instance. When used with
+ /// Configure() this is the count of caller-supplied servers. If the
+ /// DnsServerListCount is zero, the DNS server configuration
+ /// will be retrieved from DHCP server automatically.
+ ///
+ UINT32 DnsServerCount;
+ ///
+ /// Pointer to DNS server list containing DnsServerListCount
+ /// entries or NULL if DnsServerListCount is 0. For Configure(),
+ /// this will be NULL when there are no caller supplied server addresses
+ /// and the DNS instance will retrieve DNS server from DHCP Server.
+ /// The provided DNS server list is recommended to be filled up in the sequence
+ /// of preference. When used with GetModeData(), the buffer containing the list
+ /// will be allocated by the driver implementing this protocol and must be
+ /// freed by the caller. When used with Configure(), the buffer
+ /// containing the list will be allocated and released by the caller.
+ ///
+ EFI_IPv6_ADDRESS *DnsServerList;
+ ///
+ /// Retry number if no response received after RetryInterval.
+ ///
+ UINT32 RetryCount;
+ ///
+ /// Minimum interval of retry is 2 second. If the retry interval is less than 2
+ /// seconds, then use the 2 seconds.
+ UINT32 RetryInterval;
+} EFI_DNS6_CONFIG_DATA;
+
+///
+/// EFI_DNS6_CACHE_ENTRY
+///
+typedef struct {
+ ///
+ /// Host name. This should be interpreted as Unicode characters.
+ ///
+ CHAR16 *HostName;
+ ///
+ /// IP address of this host.
+ ///
+ EFI_IPv6_ADDRESS *IpAddress;
+ ///
+ /// Time in second unit that this entry will remain in DNS cache. A value of zero means
+ /// that this entry is permanent. A nonzero value will override the existing one if
+ /// this entry to be added is dynamic entry. Implementations may set its default
+ /// timeout value for the dynamically created DNS cache entry after one DNS resolve
+ /// succeeds.
+ UINT32 Timeout;
+} EFI_DNS6_CACHE_ENTRY;
+
+///
+/// EFI_DNS6_MODE_DATA
+///
+typedef struct {
+ ///
+ /// The configuration data of this instance.
+ ///
+ EFI_DNS6_CONFIG_DATA DnsConfigData;
+ ///
+ /// Number of configured DNS6 servers.
+ ///
+ UINT32 DnsServerCount;
+ ///
+ /// Pointer to common list of addresses of all configured DNS server used by EFI_DNS6_PROTOCOL
+ /// instances. List will include DNS servers configured by this or any other EFI_DNS6_PROTOCOL
+ /// instance. The storage for this list is allocated by the driver publishing this protocol,
+ /// and must be freed by the caller.
+ ///
+ EFI_IPv6_ADDRESS *DnsServerList;
+ ///
+ /// Number of DNS Cache entries. The DNS Cache is shared among all DNS instances.
+ ///
+ UINT32 DnsCacheCount;
+ ///
+ /// Pointer to a buffer containing DnsCacheCount DNS Cache
+ /// entry structures. The storage for thislist is allocated by the driver
+ /// publishing this protocol and must be freed by caller.
+ ///
+ EFI_DNS6_CACHE_ENTRY *DnsCacheList;
+} EFI_DNS6_MODE_DATA;
+
+///
+/// DNS6_HOST_TO_ADDR_DATA
+///
+typedef struct {
+ ///
+ /// Number of the returned IP address.
+ ///
+ UINT32 IpCount;
+ ///
+ /// Pointer to the all the returned IP address.
+ ///
+ EFI_IPv6_ADDRESS *IpList;
+} DNS6_HOST_TO_ADDR_DATA;
+
+///
+/// DNS6_ADDR_TO_HOST_DATA
+///
+typedef struct {
+ ///
+ /// Pointer to the primary name for this host address. It's the caller's
+ /// responsibility to free the response memory.
+ ///
+ CHAR16 *HostName;
+} DNS6_ADDR_TO_HOST_DATA;
+
+///
+/// DNS6_RESOURCE_RECORD
+///
+typedef struct {
+ ///
+ /// The Owner name.
+ ///
+ CHAR8 *QName;
+ ///
+ /// The Type Code of this RR.
+ ///
+ UINT16 QType;
+ ///
+ /// The CLASS code of this RR.
+ ///
+ UINT16 QClass;
+ ///
+ /// 32 bit integer which specify the time interval that the resource record may be
+ /// cached before the source of the information should again be consulted. Zero means
+ /// this RR cannot be cached.
+ ///
+ UINT32 TTL;
+ ///
+ /// 16 big integer which specify the length of RData.
+ ///
+ UINT16 DataLength;
+ ///
+ /// A string of octets that describe the resource, the format of this information
+ /// varies according to QType and QClass difference.
+ ///
+ CHAR8 *RData;
+} DNS6_RESOURCE_RECORD;
+
+///
+/// DNS6_GENERAL_LOOKUP_DATA
+///
+typedef struct {
+ ///
+ /// Number of returned matching RRs.
+ ///
+ UINTN RRCount;
+ ///
+ /// Pointer to the all the returned matching RRs. It's caller responsibility to free
+ /// the allocated memory to hold the returned RRs.
+ ///
+ DNS6_RESOURCE_RECORD *RRList;
+} DNS6_GENERAL_LOOKUP_DATA;
+
+///
+/// EFI_DNS6_COMPLETION_TOKEN
+///
+typedef struct {
+ ///
+ /// This Event will be signaled after the Status field is updated by the EFI DNSv6
+ /// protocol driver. The type of Event must be EFI_NOTIFY_SIGNAL.
+ ///
+ EFI_EVENT Event;
+ ///
+ /// Will be set to one of the following values:
+ /// EFI_SUCCESS: The host name to address translation completed successfully.
+ /// EFI_NOT_FOUND: No matching Resource Record (RR) is found.
+ /// EFI_TIMEOUT: No DNS server reachable, or RetryCount was exhausted without
+ /// response from all specified DNS servers.
+ /// EFI_DEVICE_ERROR: An unexpected system or network error occurred.
+ /// EFI_NO_MEDIA: There was a media error.
+ ///
+ EFI_STATUS Status;
+ ///
+ /// The parameter configured through DNSv6.Configure() interface. Retry number if no
+ /// response received after RetryInterval.
+ ///
+ UINT32 RetryCount;
+ ///
+ /// The parameter configured through DNSv6.Configure() interface. Minimum interval of
+ /// retry is 2 seconds. If the retry interval is less than 2 seconds, then use the 2
+ /// seconds.
+ ///
+ UINT32 RetryInterval;
+ ///
+ /// DNSv6 completion token data
+ ///
+ union {
+ ///
+ /// When the Token is used for host name to address translation, H2AData is a pointer
+ /// to the DNS6_HOST_TO_ADDR_DATA.
+ ///
+ DNS6_HOST_TO_ADDR_DATA *H2AData;
+ ///
+ /// When the Token is used for host address to host name translation, A2HData is a
+ /// pointer to the DNS6_ADDR_TO_HOST_DATA.
+ ///
+ DNS6_ADDR_TO_HOST_DATA *A2HData;
+ ///
+ /// When the Token is used for a general lookup function, GLookupDATA is a pointer to
+ /// the DNS6_GENERAL_LOOKUP_DATA.
+ ///
+ DNS6_GENERAL_LOOKUP_DATA *GLookupData;
+ } RspData;
+} EFI_DNS6_COMPLETION_TOKEN;
+
+/**
+ Retrieve mode data of this DNS instance.
+
+ This function is used to retrieve DNS mode data for this DNS instance.
+
+ @param[in] This Pointer to EFI_DNS6_PROTOCOL instance.
+ @param[out] DnsModeData Pointer to the caller-allocated storage for the
+ EFI_DNS6_MODE_DATA data.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_NOT_STARTED When DnsConfigData is queried, no configuration data
+ is available because this instance has not been
+ configured.
+ @retval EFI_INVALID_PARAMETER This is NULL or DnsModeData is NULL.
+ @retval EFI_OUT_OF_RESOURCE Failed to allocate needed resources.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DNS6_GET_MODE_DATA)(
+ IN EFI_DNS6_PROTOCOL *This,
+ OUT EFI_DNS6_MODE_DATA *DnsModeData
+ );
+
+/**
+ Configure this DNS instance.
+
+ The Configure() function is used to set and change the configuration data for this
+ EFI DNSv6 Protocol driver instance. Reset the DNS instance if DnsConfigData is NULL.
+
+ @param[in] This Pointer to EFI_DNS6_PROTOCOL instance.
+ @param[in] DnsConfigData Pointer to the configuration data structure. All associated
+ storage to be allocated and released by caller.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ The StationIp address provided in DnsConfigData is not zero and not a valid unicast.
+ DnsServerList is NULL while DnsServerList Count is not ZERO.
+ DnsServerList Count is ZERO while DnsServerList is not NULL.
+ @retval EFI_OUT_OF_RESOURCES The DNS instance data or required space could not be allocated.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The
+ EFI DNSv6 Protocol instance is not configured.
+ @retval EFI_UNSUPPORTED The designated protocol is not supported.
+ @retval EFI_ALREADY_STARTED Second call to Configure() with DnsConfigData. To
+ reconfigure the instance the caller must call Configure() with
+ NULL first to return driver to unconfigured state.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DNS6_CONFIGURE)(
+ IN EFI_DNS6_PROTOCOL *This,
+ IN EFI_DNS6_CONFIG_DATA *DnsConfigData
+ );
+
+/**
+ Host name to host address translation.
+
+ The HostNameToIp () function is used to translate the host name to host IP address. A
+ type AAAA query is used to get the one or more IPv6 addresses for this host.
+
+ @param[in] This Pointer to EFI_DNS6_PROTOCOL instance.
+ @param[in] HostName Host name.
+ @param[in] Token Point to the completion token to translate host name
+ to host address.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ Token is NULL.
+ Token.Event is NULL.
+ HostName is NULL or buffer contained unsupported characters.
+ @retval EFI_NO_MAPPING There's no source address is available for use.
+ @retval EFI_ALREADY_STARTED This Token is being used in another DNS session.
+ @retval EFI_NOT_STARTED This instance has not been started.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DNS6_HOST_NAME_TO_IP)(
+ IN EFI_DNS6_PROTOCOL *This,
+ IN CHAR16 *HostName,
+ IN EFI_DNS6_COMPLETION_TOKEN *Token
+ );
+
+/**
+ Host address to host name translation.
+
+ The IpToHostName () function is used to translate the host address to host name. A
+ type PTR query is used to get the primary name of the host. Implementation can choose
+ to support this function or not.
+
+ @param[in] This Pointer to EFI_DNS6_PROTOCOL instance.
+ @param[in] IpAddress Ip Address.
+ @param[in] Token Point to the completion token to translate host
+ address to host name.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_UNSUPPORTED This function is not supported.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ Token is NULL.
+ Token.Event is NULL.
+ IpAddress is not valid IP address.
+ @retval EFI_NO_MAPPING There's no source address is available for use.
+ @retval EFI_NOT_STARTED This instance has not been started.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DNS6_IP_TO_HOST_NAME)(
+ IN EFI_DNS6_PROTOCOL *This,
+ IN EFI_IPv6_ADDRESS IpAddress,
+ IN EFI_DNS6_COMPLETION_TOKEN *Token
+ );
+
+/**
+ This function provides capability to retrieve arbitrary information from the DNS
+ server.
+
+ This GeneralLookup() function retrieves arbitrary information from the DNS. The caller
+ supplies a QNAME, QTYPE, and QCLASS, and all of the matching RRs are returned. All
+ RR content (e.g., TTL) was returned. The caller need parse the returned RR to get
+ required information. The function is optional. Implementation can choose to support
+ it or not.
+
+ @param[in] This Pointer to EFI_DNS6_PROTOCOL instance.
+ @param[in] QName Pointer to Query Name.
+ @param[in] QType Query Type.
+ @param[in] QClass Query Name.
+ @param[in] Token Point to the completion token to retrieve arbitrary
+ information.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_UNSUPPORTED This function is not supported. Or the requested
+ QType is not supported
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ Token is NULL.
+ Token.Event is NULL.
+ QName is NULL.
+ @retval EFI_NO_MAPPING There's no source address is available for use.
+ @retval EFI_NOT_STARTED This instance has not been started.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DNS6_GENERAL_LOOKUP)(
+ IN EFI_DNS6_PROTOCOL *This,
+ IN CHAR8 *QName,
+ IN UINT16 QType,
+ IN UINT16 QClass,
+ IN EFI_DNS6_COMPLETION_TOKEN *Token
+ );
+
+/**
+ This function is to update the DNS Cache.
+
+ The UpdateDnsCache() function is used to add/delete/modify DNS cache entry. DNS cache
+ can be normally dynamically updated after the DNS resolve succeeds. This function
+ provided capability to manually add/delete/modify the DNS cache.
+
+ @param[in] This Pointer to EFI_DNS6_PROTOCOL instance.
+ @param[in] DeleteFlag If FALSE, this function is to add one entry to the
+ DNS Cahce. If TRUE, this function will delete
+ matching DNS Cache entry.
+ @param[in] Override If TRUE, the maching DNS cache entry will be
+ overwritten with the supplied parameter. If FALSE,
+ EFI_ACCESS_DENIED will be returned if the entry to
+ be added is already existed.
+ @param[in] DnsCacheEntry Pointer to DNS Cache entry.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ DnsCacheEntry.HostName is NULL.
+ DnsCacheEntry.IpAddress is NULL.
+ DnsCacheEntry.Timeout is zero.
+ @retval EFI_ACCESS_DENIED The DNS cache entry already exists and Override is
+ not TRUE.
+ @retval EFI_OUT_OF_RESOURCE Failed to allocate needed resources.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DNS6_UPDATE_DNS_CACHE)(
+ IN EFI_DNS6_PROTOCOL *This,
+ IN BOOLEAN DeleteFlag,
+ IN BOOLEAN Override,
+ IN EFI_DNS6_CACHE_ENTRY DnsCacheEntry
+ );
+
+/**
+ Polls for incoming data packets and processes outgoing data packets.
+
+ The Poll() function can be used by network drivers and applications to increase the
+ rate that data packets are moved between the communications device and the transmit
+ and receive queues.
+
+ In some systems, the periodic timer event in the managed network driver may not poll
+ the underlying communications device fast enough to transmit and/or receive all data
+ packets without missing incoming packets or dropping outgoing packets. Drivers and
+ applications that are experiencing packet loss should try calling the Poll()
+ function more often.
+
+ @param[in] This Pointer to EFI_DNS6_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Incoming or outgoing data was processed.
+ @retval EFI_NOT_STARTED This EFI DNS Protocol instance has not been started.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_NO_MAPPING There is no source address is available for use.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive
+ queue. Consider increasing the polling rate.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DNS6_POLL)(
+ IN EFI_DNS6_PROTOCOL *This
+ );
+
+/**
+ Abort an asynchronous DNS operation, including translation between IP and Host, and
+ general look up behavior.
+
+ The Cancel() function is used to abort a pending resolution request. After calling
+ this function, Token.Status will be set to EFI_ABORTED and then Token.Event will be
+ signaled. If the token is not in one of the queues, which usually means that the
+ asynchronous operation has completed, this function will not signal the token and
+ EFI_NOT_FOUND is returned.
+
+ @param[in] This Pointer to EFI_DNS6_PROTOCOL instance.
+ @param[in] Token Pointer to a token that has been issued by
+ EFI_DNS6_PROTOCOL.HostNameToIp (),
+ EFI_DNS6_PROTOCOL.IpToHostName() or
+ EFI_DNS6_PROTOCOL.GeneralLookup().
+ If NULL, all pending tokens are aborted.
+
+ @retval EFI_SUCCESS Incoming or outgoing data was processed.
+ @retval EFI_NOT_STARTED This EFI DNS6 Protocol instance has not been started.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_NO_MAPPING There's no source address is available for use.
+ @retval EFI_NOT_FOUND When Token is not NULL, and the asynchronous DNS
+ operation was not found in the transmit queue. It
+ was either completed or was not issued by
+ HostNameToIp(), IpToHostName() or GeneralLookup().
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DNS6_CANCEL)(
+ IN EFI_DNS6_PROTOCOL *This,
+ IN EFI_DNS6_COMPLETION_TOKEN *Token
+ );
+
+///
+/// The EFI_DNS6_PROTOCOL provides the function to get the host name and address
+/// mapping, also provide pass through interface to retrieve arbitrary information from
+/// DNSv6.
+///
+struct _EFI_DNS6_PROTOCOL {
+ EFI_DNS6_GET_MODE_DATA GetModeData;
+ EFI_DNS6_CONFIGURE Configure;
+ EFI_DNS6_HOST_NAME_TO_IP HostNameToIp;
+ EFI_DNS6_IP_TO_HOST_NAME IpToHostName;
+ EFI_DNS6_GENERAL_LOOKUP GeneralLookUp;
+ EFI_DNS6_UPDATE_DNS_CACHE UpdateDnsCache;
+ EFI_DNS6_POLL Poll;
+ EFI_DNS6_CANCEL Cancel;
+};
+
+extern EFI_GUID gEfiDns6ServiceBindingProtocolGuid;
+extern EFI_GUID gEfiDns6ProtocolGuid;
+
+#endif
diff --git a/src/include/ipxe/efi/Protocol/Http.h b/src/include/ipxe/efi/Protocol/Http.h
new file mode 100644
index 00000000..d30a5aa4
--- /dev/null
+++ b/src/include/ipxe/efi/Protocol/Http.h
@@ -0,0 +1,516 @@
+/** @file
+ This file defines the EFI HTTP Protocol interface. It is split into
+ the following two main sections:
+ HTTP Service Binding Protocol (HTTPSB)
+ HTTP Protocol (HTTP)
+
+ Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2015-2017 Hewlett Packard Enterprise Development LP<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Revision Reference:
+ This Protocol is introduced in UEFI Specification 2.5
+
+**/
+
+#ifndef __EFI_HTTP_PROTOCOL_H__
+#define __EFI_HTTP_PROTOCOL_H__
+
+FILE_LICENCE ( BSD2_PATENT );
+
+#define EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID \
+ { \
+ 0xbdc8e6af, 0xd9bc, 0x4379, {0xa7, 0x2a, 0xe0, 0xc4, 0xe7, 0x5d, 0xae, 0x1c } \
+ }
+
+#define EFI_HTTP_PROTOCOL_GUID \
+ { \
+ 0x7a59b29b, 0x910b, 0x4171, {0x82, 0x42, 0xa8, 0x5a, 0x0d, 0xf2, 0x5b, 0x5b } \
+ }
+
+typedef struct _EFI_HTTP_PROTOCOL EFI_HTTP_PROTOCOL;
+
+///
+/// EFI_HTTP_VERSION
+///
+typedef enum {
+ HttpVersion10,
+ HttpVersion11,
+ HttpVersionUnsupported
+} EFI_HTTP_VERSION;
+
+///
+/// EFI_HTTP_METHOD
+///
+typedef enum {
+ HttpMethodGet,
+ HttpMethodPost,
+ HttpMethodPatch,
+ HttpMethodOptions,
+ HttpMethodConnect,
+ HttpMethodHead,
+ HttpMethodPut,
+ HttpMethodDelete,
+ HttpMethodTrace,
+ HttpMethodMax
+} EFI_HTTP_METHOD;
+
+///
+/// EFI_HTTP_STATUS_CODE
+///
+typedef enum {
+ HTTP_STATUS_UNSUPPORTED_STATUS = 0,
+ HTTP_STATUS_100_CONTINUE,
+ HTTP_STATUS_101_SWITCHING_PROTOCOLS,
+ HTTP_STATUS_200_OK,
+ HTTP_STATUS_201_CREATED,
+ HTTP_STATUS_202_ACCEPTED,
+ HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION,
+ HTTP_STATUS_204_NO_CONTENT,
+ HTTP_STATUS_205_RESET_CONTENT,
+ HTTP_STATUS_206_PARTIAL_CONTENT,
+ HTTP_STATUS_300_MULTIPLE_CHOICES,
+ HTTP_STATUS_301_MOVED_PERMANENTLY,
+ HTTP_STATUS_302_FOUND,
+ HTTP_STATUS_303_SEE_OTHER,
+ HTTP_STATUS_304_NOT_MODIFIED,
+ HTTP_STATUS_305_USE_PROXY,
+ HTTP_STATUS_307_TEMPORARY_REDIRECT,
+ HTTP_STATUS_400_BAD_REQUEST,
+ HTTP_STATUS_401_UNAUTHORIZED,
+ HTTP_STATUS_402_PAYMENT_REQUIRED,
+ HTTP_STATUS_403_FORBIDDEN,
+ HTTP_STATUS_404_NOT_FOUND,
+ HTTP_STATUS_405_METHOD_NOT_ALLOWED,
+ HTTP_STATUS_406_NOT_ACCEPTABLE,
+ HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED,
+ HTTP_STATUS_408_REQUEST_TIME_OUT,
+ HTTP_STATUS_409_CONFLICT,
+ HTTP_STATUS_410_GONE,
+ HTTP_STATUS_411_LENGTH_REQUIRED,
+ HTTP_STATUS_412_PRECONDITION_FAILED,
+ HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE,
+ HTTP_STATUS_414_REQUEST_URI_TOO_LARGE,
+ HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE,
+ HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED,
+ HTTP_STATUS_417_EXPECTATION_FAILED,
+ HTTP_STATUS_500_INTERNAL_SERVER_ERROR,
+ HTTP_STATUS_501_NOT_IMPLEMENTED,
+ HTTP_STATUS_502_BAD_GATEWAY,
+ HTTP_STATUS_503_SERVICE_UNAVAILABLE,
+ HTTP_STATUS_504_GATEWAY_TIME_OUT,
+ HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED,
+ HTTP_STATUS_308_PERMANENT_REDIRECT
+} EFI_HTTP_STATUS_CODE;
+
+///
+/// EFI_HTTPv4_ACCESS_POINT
+///
+typedef struct {
+ ///
+ /// Set to TRUE to instruct the EFI HTTP instance to use the default address
+ /// information in every TCP connection made by this instance. In addition, when set
+ /// to TRUE, LocalAddress and LocalSubnet are ignored.
+ ///
+ BOOLEAN UseDefaultAddress;
+ ///
+ /// If UseDefaultAddress is set to FALSE, this defines the local IP address to be
+ /// used in every TCP connection opened by this instance.
+ ///
+ EFI_IPv4_ADDRESS LocalAddress;
+ ///
+ /// If UseDefaultAddress is set to FALSE, this defines the local subnet to be used
+ /// in every TCP connection opened by this instance.
+ ///
+ EFI_IPv4_ADDRESS LocalSubnet;
+ ///
+ /// This defines the local port to be used in
+ /// every TCP connection opened by this instance.
+ ///
+ UINT16 LocalPort;
+} EFI_HTTPv4_ACCESS_POINT;
+
+///
+/// EFI_HTTPv6_ACCESS_POINT
+///
+typedef struct {
+ ///
+ /// Local IP address to be used in every TCP connection opened by this instance.
+ ///
+ EFI_IPv6_ADDRESS LocalAddress;
+ ///
+ /// Local port to be used in every TCP connection opened by this instance.
+ ///
+ UINT16 LocalPort;
+} EFI_HTTPv6_ACCESS_POINT;
+
+///
+/// EFI_HTTP_CONFIG_DATA_ACCESS_POINT
+///
+
+typedef struct {
+ ///
+ /// HTTP version that this instance will support.
+ ///
+ EFI_HTTP_VERSION HttpVersion;
+ ///
+ /// Time out (in milliseconds) when blocking for requests.
+ ///
+ UINT32 TimeOutMillisec;
+ ///
+ /// Defines behavior of EFI DNS and TCP protocols consumed by this instance. If
+ /// FALSE, this instance will use EFI_DNS4_PROTOCOL and EFI_TCP4_PROTOCOL. If TRUE,
+ /// this instance will use EFI_DNS6_PROTOCOL and EFI_TCP6_PROTOCOL.
+ ///
+ BOOLEAN LocalAddressIsIPv6;
+
+ union {
+ ///
+ /// When LocalAddressIsIPv6 is FALSE, this points to the local address, subnet, and
+ /// port used by the underlying TCP protocol.
+ ///
+ EFI_HTTPv4_ACCESS_POINT *IPv4Node;
+ ///
+ /// When LocalAddressIsIPv6 is TRUE, this points to the local IPv6 address and port
+ /// used by the underlying TCP protocol.
+ ///
+ EFI_HTTPv6_ACCESS_POINT *IPv6Node;
+ } AccessPoint;
+} EFI_HTTP_CONFIG_DATA;
+
+///
+/// EFI_HTTP_REQUEST_DATA
+///
+typedef struct {
+ ///
+ /// The HTTP method (e.g. GET, POST) for this HTTP Request.
+ ///
+ EFI_HTTP_METHOD Method;
+ ///
+ /// The URI of a remote host. From the information in this field, the HTTP instance
+ /// will be able to determine whether to use HTTP or HTTPS and will also be able to
+ /// determine the port number to use. If no port number is specified, port 80 (HTTP)
+ /// is assumed. See RFC 3986 for more details on URI syntax.
+ ///
+ CHAR16 *Url;
+} EFI_HTTP_REQUEST_DATA;
+
+///
+/// EFI_HTTP_RESPONSE_DATA
+///
+typedef struct {
+ ///
+ /// Response status code returned by the remote host.
+ ///
+ EFI_HTTP_STATUS_CODE StatusCode;
+} EFI_HTTP_RESPONSE_DATA;
+
+///
+/// EFI_HTTP_HEADER
+///
+typedef struct {
+ ///
+ /// Null terminated string which describes a field name. See RFC 2616 Section 14 for
+ /// detailed information about field names.
+ ///
+ CHAR8 *FieldName;
+ ///
+ /// Null terminated string which describes the corresponding field value. See RFC 2616
+ /// Section 14 for detailed information about field values.
+ ///
+ CHAR8 *FieldValue;
+} EFI_HTTP_HEADER;
+
+///
+/// EFI_HTTP_MESSAGE
+///
+typedef struct {
+ ///
+ /// HTTP message data.
+ ///
+ union {
+ ///
+ /// When the token is used to send a HTTP request, Request is a pointer to storage that
+ /// contains such data as URL and HTTP method.
+ ///
+ EFI_HTTP_REQUEST_DATA *Request;
+ ///
+ /// When used to await a response, Response points to storage containing HTTP response
+ /// status code.
+ ///
+ EFI_HTTP_RESPONSE_DATA *Response;
+ } Data;
+ ///
+ /// Number of HTTP header structures in Headers list. On request, this count is
+ /// provided by the caller. On response, this count is provided by the HTTP driver.
+ ///
+ UINTN HeaderCount;
+ ///
+ /// Array containing list of HTTP headers. On request, this array is populated by the
+ /// caller. On response, this array is allocated and populated by the HTTP driver. It
+ /// is the responsibility of the caller to free this memory on both request and
+ /// response.
+ ///
+ EFI_HTTP_HEADER *Headers;
+ ///
+ /// Length in bytes of the HTTP body. This can be zero depending on the HttpMethod type.
+ ///
+ UINTN BodyLength;
+ ///
+ /// Body associated with the HTTP request or response. This can be NULL depending on
+ /// the HttpMethod type.
+ ///
+ VOID *Body;
+} EFI_HTTP_MESSAGE;
+
+///
+/// EFI_HTTP_TOKEN
+///
+typedef struct {
+ ///
+ /// This Event will be signaled after the Status field is updated by the EFI HTTP
+ /// Protocol driver. The type of Event must be EFI_NOTIFY_SIGNAL. The Task Priority
+ /// Level (TPL) of Event must be lower than or equal to TPL_CALLBACK.
+ ///
+ EFI_EVENT Event;
+ ///
+ /// Status will be set to one of the following value if the HTTP request is
+ /// successfully sent or if an unexpected error occurs:
+ /// EFI_SUCCESS: The HTTP request was successfully sent to the remote host.
+ /// EFI_HTTP_ERROR: The response message was successfully received but contains a
+ /// HTTP error. The response status code is returned in token.
+ /// EFI_ABORTED: The HTTP request was cancelled by the caller and removed from
+ /// the transmit queue.
+ /// EFI_TIMEOUT: The HTTP request timed out before reaching the remote host.
+ /// EFI_DEVICE_ERROR: An unexpected system or network error occurred.
+ ///
+ EFI_STATUS Status;
+ ///
+ /// Pointer to storage containing HTTP message data.
+ ///
+ EFI_HTTP_MESSAGE *Message;
+} EFI_HTTP_TOKEN;
+
+/**
+ Returns the operational parameters for the current HTTP child instance.
+
+ The GetModeData() function is used to read the current mode data (operational
+ parameters) for this HTTP protocol instance.
+
+ @param[in] This Pointer to EFI_HTTP_PROTOCOL instance.
+ @param[out] HttpConfigData Point to buffer for operational parameters of this
+ HTTP instance. It is the responsibility of the caller
+ to allocate the memory for HttpConfigData and
+ HttpConfigData->AccessPoint.IPv6Node/IPv4Node. In fact,
+ it is recommended to allocate sufficient memory to record
+ IPv6Node since it is big enough for all possibilities.
+
+ @retval EFI_SUCCESS Operation succeeded.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ HttpConfigData is NULL.
+ HttpConfigData->AccessPoint.IPv4Node or
+ HttpConfigData->AccessPoint.IPv6Node is NULL.
+ @retval EFI_NOT_STARTED This EFI HTTP Protocol instance has not been started.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HTTP_GET_MODE_DATA)(
+ IN EFI_HTTP_PROTOCOL *This,
+ OUT EFI_HTTP_CONFIG_DATA *HttpConfigData
+ );
+
+/**
+ Initialize or brutally reset the operational parameters for this EFI HTTP instance.
+
+ The Configure() function does the following:
+ When HttpConfigData is not NULL Initialize this EFI HTTP instance by configuring
+ timeout, local address, port, etc.
+ When HttpConfigData is NULL, reset this EFI HTTP instance by closing all active
+ connections with remote hosts, canceling all asynchronous tokens, and flush request
+ and response buffers without informing the appropriate hosts.
+
+ No other EFI HTTP function can be executed by this instance until the Configure()
+ function is executed and returns successfully.
+
+ @param[in] This Pointer to EFI_HTTP_PROTOCOL instance.
+ @param[in] HttpConfigData Pointer to the configure data to configure the instance.
+
+ @retval EFI_SUCCESS Operation succeeded.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ HttpConfigData->LocalAddressIsIPv6 is FALSE and
+ HttpConfigData->AccessPoint.IPv4Node is NULL.
+ HttpConfigData->LocalAddressIsIPv6 is TRUE and
+ HttpConfigData->AccessPoint.IPv6Node is NULL.
+ @retval EFI_ALREADY_STARTED Reinitialize this HTTP instance without calling
+ Configure() with NULL to reset it.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources when
+ executing Configure().
+ @retval EFI_UNSUPPORTED One or more options in ConfigData are not supported
+ in the implementation.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HTTP_CONFIGURE)(
+ IN EFI_HTTP_PROTOCOL *This,
+ IN EFI_HTTP_CONFIG_DATA *HttpConfigData OPTIONAL
+ );
+
+/**
+ The Request() function queues an HTTP request to this HTTP instance,
+ similar to Transmit() function in the EFI TCP driver. When the HTTP request is sent
+ successfully, or if there is an error, Status in token will be updated and Event will
+ be signaled.
+
+ @param[in] This Pointer to EFI_HTTP_PROTOCOL instance.
+ @param[in] Token Pointer to storage containing HTTP request token.
+
+ @retval EFI_SUCCESS Outgoing data was processed.
+ @retval EFI_NOT_STARTED This EFI HTTP Protocol instance has not been started.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_TIMEOUT Data was dropped out of the transmit or receive queue.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ Token is NULL.
+ Token->Message is NULL.
+ Token->Message->Body is not NULL,
+ Token->Message->BodyLength is non-zero, and
+ Token->Message->Data is NULL, but a previous call to
+ Request()has not been completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources.
+ @retval EFI_UNSUPPORTED The HTTP method is not supported in current implementation.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HTTP_REQUEST)(
+ IN EFI_HTTP_PROTOCOL *This,
+ IN EFI_HTTP_TOKEN *Token
+ );
+
+/**
+ Abort an asynchronous HTTP request or response token.
+
+ The Cancel() function aborts a pending HTTP request or response transaction. If
+ Token is not NULL and the token is in transmit or receive queues when it is being
+ cancelled, its Token->Status will be set to EFI_ABORTED and then Token->Event will
+ be signaled. If the token is not in one of the queues, which usually means that the
+ asynchronous operation has completed, EFI_NOT_FOUND is returned. If Token is NULL,
+ all asynchronous tokens issued by Request() or Response() will be aborted.
+
+ @param[in] This Pointer to EFI_HTTP_PROTOCOL instance.
+ @param[in] Token Point to storage containing HTTP request or response
+ token.
+
+ @retval EFI_SUCCESS Request and Response queues are successfully flushed.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_NOT_STARTED This instance hasn't been configured.
+ @retval EFI_NOT_FOUND The asynchronous request or response token is not
+ found.
+ @retval EFI_UNSUPPORTED The implementation does not support this function.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HTTP_CANCEL)(
+ IN EFI_HTTP_PROTOCOL *This,
+ IN EFI_HTTP_TOKEN *Token
+ );
+
+/**
+ The Response() function queues an HTTP response to this HTTP instance, similar to
+ Receive() function in the EFI TCP driver. When the HTTP Response is received successfully,
+ or if there is an error, Status in token will be updated and Event will be signaled.
+
+ The HTTP driver will queue a receive token to the underlying TCP instance. When data
+ is received in the underlying TCP instance, the data will be parsed and Token will
+ be populated with the response data. If the data received from the remote host
+ contains an incomplete or invalid HTTP header, the HTTP driver will continue waiting
+ (asynchronously) for more data to be sent from the remote host before signaling
+ Event in Token.
+
+ It is the responsibility of the caller to allocate a buffer for Body and specify the
+ size in BodyLength. If the remote host provides a response that contains a content
+ body, up to BodyLength bytes will be copied from the receive buffer into Body and
+ BodyLength will be updated with the amount of bytes received and copied to Body. This
+ allows the client to download a large file in chunks instead of into one contiguous
+ block of memory. Similar to HTTP request, if Body is not NULL and BodyLength is
+ non-zero and all other fields are NULL or 0, the HTTP driver will queue a receive
+ token to underlying TCP instance. If data arrives in the receive buffer, up to
+ BodyLength bytes of data will be copied to Body. The HTTP driver will then update
+ BodyLength with the amount of bytes received and copied to Body.
+
+ If the HTTP driver does not have an open underlying TCP connection with the host
+ specified in the response URL, Request() will return EFI_ACCESS_DENIED. This is
+ consistent with RFC 2616 recommendation that HTTP clients should attempt to maintain
+ an open TCP connection between client and host.
+
+ @param[in] This Pointer to EFI_HTTP_PROTOCOL instance.
+ @param[in] Token Pointer to storage containing HTTP response token.
+
+ @retval EFI_SUCCESS Allocation succeeded.
+ @retval EFI_NOT_STARTED This EFI HTTP Protocol instance has not been
+ initialized.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ Token is NULL.
+ Token->Message->Headers is NULL.
+ Token->Message is NULL.
+ Token->Message->Body is not NULL,
+ Token->Message->BodyLength is non-zero, and
+ Token->Message->Data is NULL, but a previous call to
+ Response() has not been completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources.
+ @retval EFI_ACCESS_DENIED An open TCP connection is not present with the host
+ specified by response URL.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HTTP_RESPONSE)(
+ IN EFI_HTTP_PROTOCOL *This,
+ IN EFI_HTTP_TOKEN *Token
+ );
+
+/**
+ The Poll() function can be used by network drivers and applications to increase the
+ rate that data packets are moved between the communication devices and the transmit
+ and receive queues.
+
+ In some systems, the periodic timer event in the managed network driver may not poll
+ the underlying communications device fast enough to transmit and/or receive all data
+ packets without missing incoming packets or dropping outgoing packets. Drivers and
+ applications that are experiencing packet loss should try calling the Poll() function
+ more often.
+
+ @param[in] This Pointer to EFI_HTTP_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Incoming or outgoing data was processed..
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_NOT_READY No incoming or outgoing data is processed.
+ @retval EFI_NOT_STARTED This EFI HTTP Protocol instance has not been started.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HTTP_POLL)(
+ IN EFI_HTTP_PROTOCOL *This
+ );
+
+///
+/// The EFI HTTP protocol is designed to be used by EFI drivers and applications to
+/// create and transmit HTTP Requests, as well as handle HTTP responses that are
+/// returned by a remote host. This EFI protocol uses and relies on an underlying EFI
+/// TCP protocol.
+///
+struct _EFI_HTTP_PROTOCOL {
+ EFI_HTTP_GET_MODE_DATA GetModeData;
+ EFI_HTTP_CONFIGURE Configure;
+ EFI_HTTP_REQUEST Request;
+ EFI_HTTP_CANCEL Cancel;
+ EFI_HTTP_RESPONSE Response;
+ EFI_HTTP_POLL Poll;
+};
+
+extern EFI_GUID gEfiHttpServiceBindingProtocolGuid;
+extern EFI_GUID gEfiHttpProtocolGuid;
+
+#endif
diff --git a/src/include/ipxe/efi/Protocol/Ip4Config2.h b/src/include/ipxe/efi/Protocol/Ip4Config2.h
new file mode 100644
index 00000000..ca091dea
--- /dev/null
+++ b/src/include/ipxe/efi/Protocol/Ip4Config2.h
@@ -0,0 +1,318 @@
+/** @file
+ This file provides a definition of the EFI IPv4 Configuration II
+ Protocol.
+
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+@par Revision Reference:
+This Protocol is introduced in UEFI Specification 2.5
+
+**/
+
+#ifndef __EFI_IP4CONFIG2_PROTOCOL_H__
+#define __EFI_IP4CONFIG2_PROTOCOL_H__
+
+FILE_LICENCE ( BSD2_PATENT );
+
+#include <ipxe/efi/Protocol/Ip4.h>
+
+#define EFI_IP4_CONFIG2_PROTOCOL_GUID \
+ { \
+ 0x5b446ed1, 0xe30b, 0x4faa, {0x87, 0x1a, 0x36, 0x54, 0xec, 0xa3, 0x60, 0x80 } \
+ }
+
+typedef struct _EFI_IP4_CONFIG2_PROTOCOL EFI_IP4_CONFIG2_PROTOCOL;
+
+///
+/// EFI_IP4_CONFIG2_DATA_TYPE
+///
+typedef enum {
+ ///
+ /// The interface information of the communication device this EFI
+ /// IPv4 Configuration II Protocol instance manages. This type of
+ /// data is read only. The corresponding Data is of type
+ /// EFI_IP4_CONFIG2_INTERFACE_INFO.
+ ///
+ Ip4Config2DataTypeInterfaceInfo,
+ ///
+ /// The general configuration policy for the EFI IPv4 network stack
+ /// running on the communication device this EFI IPv4
+ /// Configuration II Protocol instance manages. The policy will
+ /// affect other configuration settings. The corresponding Data is of
+ /// type EFI_IP4_CONFIG2_POLICY.
+ ///
+ Ip4Config2DataTypePolicy,
+ ///
+ /// The station addresses set manually for the EFI IPv4 network
+ /// stack. It is only configurable when the policy is
+ /// Ip4Config2PolicyStatic. The corresponding Data is of
+ /// type EFI_IP4_CONFIG2_MANUAL_ADDRESS. When DataSize
+ /// is 0 and Data is NULL, the existing configuration is cleared
+ /// from the EFI IPv4 Configuration II Protocol instance.
+ ///
+ Ip4Config2DataTypeManualAddress,
+ ///
+ /// The gateway addresses set manually for the EFI IPv4 network
+ /// stack running on the communication device this EFI IPv4
+ /// Configuration II Protocol manages. It is not configurable when
+ /// the policy is Ip4Config2PolicyDhcp. The gateway
+ /// addresses must be unicast IPv4 addresses. The corresponding
+ /// Data is a pointer to an array of EFI_IPv4_ADDRESS instances.
+ /// When DataSize is 0 and Data is NULL, the existing configuration
+ /// is cleared from the EFI IPv4 Configuration II Protocol instance.
+ ///
+ Ip4Config2DataTypeGateway,
+ ///
+ /// The DNS server list for the EFI IPv4 network stack running on
+ /// the communication device this EFI IPv4 Configuration II
+ /// Protocol manages. It is not configurable when the policy is
+ /// Ip4Config2PolicyDhcp. The DNS server addresses must be
+ /// unicast IPv4 addresses. The corresponding Data is a pointer to
+ /// an array of EFI_IPv4_ADDRESS instances. When DataSize
+ /// is 0 and Data is NULL, the existing configuration is cleared
+ /// from the EFI IPv4 Configuration II Protocol instance.
+ ///
+ Ip4Config2DataTypeDnsServer,
+ Ip4Config2DataTypeMaximum
+} EFI_IP4_CONFIG2_DATA_TYPE;
+
+///
+/// EFI_IP4_CONFIG2_INTERFACE_INFO related definitions
+///
+#define EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE 32
+
+///
+/// EFI_IP4_CONFIG2_INTERFACE_INFO
+///
+typedef struct {
+ ///
+ /// The name of the interface. It is a NULL-terminated Unicode string.
+ ///
+ CHAR16 Name[EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE];
+ ///
+ /// The interface type of the network interface. See RFC 1700,
+ /// section "Number Hardware Type".
+ ///
+ UINT8 IfType;
+ ///
+ /// The size, in bytes, of the network interface's hardware address.
+ ///
+ UINT32 HwAddressSize;
+ ///
+ /// The hardware address for the network interface.
+ ///
+ EFI_MAC_ADDRESS HwAddress;
+ ///
+ /// The station IPv4 address of this EFI IPv4 network stack.
+ ///
+ EFI_IPv4_ADDRESS StationAddress;
+ ///
+ /// The subnet address mask that is associated with the station address.
+ ///
+ EFI_IPv4_ADDRESS SubnetMask;
+ ///
+ /// Size of the following RouteTable, in bytes. May be zero.
+ ///
+ UINT32 RouteTableSize;
+ ///
+ /// The route table of the IPv4 network stack runs on this interface.
+ /// Set to NULL if RouteTableSize is zero. Type EFI_IP4_ROUTE_TABLE is defined in
+ /// EFI_IP4_PROTOCOL.GetModeData().
+ ///
+ EFI_IP4_ROUTE_TABLE *RouteTable OPTIONAL;
+} EFI_IP4_CONFIG2_INTERFACE_INFO;
+
+///
+/// EFI_IP4_CONFIG2_POLICY
+///
+typedef enum {
+ ///
+ /// Under this policy, the Ip4Config2DataTypeManualAddress,
+ /// Ip4Config2DataTypeGateway and Ip4Config2DataTypeDnsServer configuration
+ /// data are required to be set manually. The EFI IPv4 Protocol will get all
+ /// required configuration such as IPv4 address, subnet mask and
+ /// gateway settings from the EFI IPv4 Configuration II protocol.
+ ///
+ Ip4Config2PolicyStatic,
+ ///
+ /// Under this policy, the Ip4Config2DataTypeManualAddress,
+ /// Ip4Config2DataTypeGateway and Ip4Config2DataTypeDnsServer configuration data are
+ /// not allowed to set via SetData(). All of these configurations are retrieved from DHCP
+ /// server or other auto-configuration mechanism.
+ ///
+ Ip4Config2PolicyDhcp,
+ Ip4Config2PolicyMax
+} EFI_IP4_CONFIG2_POLICY;
+
+///
+/// EFI_IP4_CONFIG2_MANUAL_ADDRESS
+///
+typedef struct {
+ ///
+ /// The IPv4 unicast address.
+ ///
+ EFI_IPv4_ADDRESS Address;
+ ///
+ /// The subnet mask.
+ ///
+ EFI_IPv4_ADDRESS SubnetMask;
+} EFI_IP4_CONFIG2_MANUAL_ADDRESS;
+
+/**
+ Set the configuration for the EFI IPv4 network stack running on the communication device this EFI
+ IPv4 Configuration II Protocol instance manages.
+
+ This function is used to set the configuration data of type DataType for the EFI IPv4 network stack
+ running on the communication device this EFI IPv4 Configuration II Protocol instance manages.
+ The successfully configured data is valid after system reset or power-off.
+ The DataSize is used to calculate the count of structure instances in the Data for some
+ DataType that multiple structure instances are allowed.
+ This function is always non-blocking. When setting some typeof configuration data, an
+ asynchronous process is invoked to check the correctness of the data, such as doing address conflict
+ detection on the manually set local IPv4 address. EFI_NOT_READY is returned immediately to
+ indicate that such an asynchronous process is invoked and the process is not finished yet. The caller
+ willing to get the result of the asynchronous process is required to call RegisterDataNotify()
+ to register an event on the specified configuration data. Once the event is signaled, the caller can call
+ GetData()to get back the configuration data in order to know the result. For other types of
+ configuration data that do not require an asynchronous configuration process, the result of the
+ operation is immediately returned.
+
+ @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
+ @param[in] DataType The type of data to set.
+ @param[in] DataSize Size of the buffer pointed to by Data in bytes.
+ @param[in] Data The data buffer to set. The type ofthe data buffer is associated
+ with the DataType.
+
+ @retval EFI_SUCCESS The specified configuration data for the EFI IPv4 network stack is set
+ successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
+ This is NULL.
+ One or more fields in Data and DataSize do not match the
+ requirement of the data type indicated by DataType.
+ @retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified configuration
+ data can not be set under the current policy.
+ @retval EFI_ACCESS_DENIED Another set operation on the specified configuration data is already in process.
+ @retval EFI_NOT_READY An asynchronous process is invoked to set the specified configuration data and
+ the process is not finished yet.
+ @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type indicated by DataType.
+ @retval EFI_UNSUPPORTED This DataType is not supported.
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+ @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP4_CONFIG2_SET_DATA)(
+ IN EFI_IP4_CONFIG2_PROTOCOL *This,
+ IN EFI_IP4_CONFIG2_DATA_TYPE DataType,
+ IN UINTN DataSize,
+ IN VOID *Data
+ );
+
+/**
+ Get the configuration data for the EFI IPv4 network stack running on the communication device this
+ EFI IPv4 Configuration II Protocol instance manages.
+
+ This function returns the configuration data of type DataType for the EFI IPv4 network stack
+ running on the communication device this EFI IPv4 Configuration II Protocol instance manages.
+ The caller is responsible for allocating the buffer usedto return the specified configuration data and
+ the required size will be returned to the caller if the size of the buffer is too small.
+ EFI_NOT_READY is returned if the specified configuration data is not ready due to an already in
+ progress asynchronous configuration process. The caller can call RegisterDataNotify() to
+ register an event on the specified configuration data. Once the asynchronous configuration process is
+ finished, the event will be signaled and a subsequent GetData() call will return the specified
+ configuration data.
+
+ @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
+ @param[in] DataType The type of data to get.
+ @param[out] DataSize On input, in bytes, the size of Data. On output, in bytes, the size
+ of buffer required to store the specified configuration data.
+ @param[in] Data The data buffer in which the configuration data is returned. The
+ type of the data buffer is associated with the DataType. Ignored
+ if DataSize is 0.
+
+ @retval EFI_SUCCESS The specified configuration data is got successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
+ This is NULL.
+ DataSize is NULL.
+ Data is NULL if *DataSizeis not zero.
+ @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified configuration data
+ and the required size is returned in DataSize.
+ @retval EFI_NOT_READY The specified configuration data is not ready due to an already in
+ progress asynchronous configuration process.
+ @retval EFI_NOT_FOUND The specified configuration data is not found.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP4_CONFIG2_GET_DATA)(
+ IN EFI_IP4_CONFIG2_PROTOCOL *This,
+ IN EFI_IP4_CONFIG2_DATA_TYPE DataType,
+ IN OUT UINTN *DataSize,
+ IN VOID *Data OPTIONAL
+ );
+
+/**
+ Register an event that is to be signaled whenever a configuration process on the specified
+ configuration data is done.
+
+ This function registers an event that is to be signaled whenever a configuration process on the
+ specified configuration data is done. An event can be registered for different DataType
+ simultaneously and the caller is responsible for determining which type of configuration data causes
+ the signaling of the event in such case.
+
+ @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
+ @param[in] DataType The type of data to unregister the event for.
+ @param[in] Event The event to register.
+
+ @retval EFI_SUCCESS The notification event for the specified configuration data is
+ registered.
+ @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
+ @retval EFI_UNSUPPORTED The configuration data type specified by DataType is not supported.
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+ @retval EFI_ACCESS_DENIED The Event is already registered for the DataType.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP4_CONFIG2_REGISTER_NOTIFY)(
+ IN EFI_IP4_CONFIG2_PROTOCOL *This,
+ IN EFI_IP4_CONFIG2_DATA_TYPE DataType,
+ IN EFI_EVENT Event
+ );
+
+/**
+ Remove a previously registered event for the specified configuration data.
+
+ This function removes a previously registeredevent for the specified configuration data.
+
+ @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
+ @param[in] DataType The type of data to remove the previously registered event for.
+ @param[in] Event The event to unregister.
+
+ @retval EFI_SUCCESS The event registered for the specified configuration data is removed.
+ @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
+ @retval EFI_NOT_FOUND The Eventhas not been registered for the specified DataType.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP4_CONFIG2_UNREGISTER_NOTIFY)(
+ IN EFI_IP4_CONFIG2_PROTOCOL *This,
+ IN EFI_IP4_CONFIG2_DATA_TYPE DataType,
+ IN EFI_EVENT Event
+ );
+
+///
+/// The EFI_IP4_CONFIG2_PROTOCOL is designed to be the central repository for the common
+/// configurations and the administrator configurable settings for the EFI IPv4 network stack.
+/// An EFI IPv4 Configuration II Protocol instance will be installed on each communication device that
+/// the EFI IPv4 network stack runs on.
+///
+struct _EFI_IP4_CONFIG2_PROTOCOL {
+ EFI_IP4_CONFIG2_SET_DATA SetData;
+ EFI_IP4_CONFIG2_GET_DATA GetData;
+ EFI_IP4_CONFIG2_REGISTER_NOTIFY RegisterDataNotify;
+ EFI_IP4_CONFIG2_UNREGISTER_NOTIFY UnregisterDataNotify;
+};
+
+extern EFI_GUID gEfiIp4Config2ProtocolGuid;
+
+#endif
diff --git a/src/include/ipxe/efi/Protocol/Ip6.h b/src/include/ipxe/efi/Protocol/Ip6.h
new file mode 100644
index 00000000..c70df190
--- /dev/null
+++ b/src/include/ipxe/efi/Protocol/Ip6.h
@@ -0,0 +1,948 @@
+/** @file
+ This file defines the EFI IPv6 (Internet Protocol version 6)
+ Protocol interface. It is split into the following three main
+ sections:
+ - EFI IPv6 Service Binding Protocol
+ - EFI IPv6 Variable (deprecated in UEFI 2.4B)
+ - EFI IPv6 Protocol
+ The EFI IPv6 Protocol provides basic network IPv6 packet I/O services,
+ which includes support for Neighbor Discovery Protocol (ND), Multicast
+ Listener Discovery Protocol (MLD), and a subset of the Internet Control
+ Message Protocol (ICMPv6).
+
+ Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Revision Reference:
+ This Protocol is introduced in UEFI Specification 2.2
+
+**/
+
+#ifndef __EFI_IP6_PROTOCOL_H__
+#define __EFI_IP6_PROTOCOL_H__
+
+FILE_LICENCE ( BSD2_PATENT );
+
+#include <ipxe/efi/Protocol/ManagedNetwork.h>
+
+#define EFI_IP6_SERVICE_BINDING_PROTOCOL_GUID \
+ { \
+ 0xec835dd3, 0xfe0f, 0x617b, {0xa6, 0x21, 0xb3, 0x50, 0xc3, 0xe1, 0x33, 0x88 } \
+ }
+
+#define EFI_IP6_PROTOCOL_GUID \
+ { \
+ 0x2c8759d5, 0x5c2d, 0x66ef, {0x92, 0x5f, 0xb6, 0x6c, 0x10, 0x19, 0x57, 0xe2 } \
+ }
+
+typedef struct _EFI_IP6_PROTOCOL EFI_IP6_PROTOCOL;
+
+///
+/// EFI_IP6_ADDRESS_PAIR is deprecated in the UEFI 2.4B and should not be used any more.
+/// The definition in here is only present to provide backwards compatability.
+///
+typedef struct {
+ ///
+ /// The EFI IPv6 Protocol instance handle that is using this address/prefix pair.
+ ///
+ EFI_HANDLE InstanceHandle;
+ ///
+ /// IPv6 address in network byte order.
+ ///
+ EFI_IPv6_ADDRESS Ip6Address;
+ ///
+ /// The length of the prefix associated with the Ip6Address.
+ ///
+ UINT8 PrefixLength;
+} EFI_IP6_ADDRESS_PAIR;
+
+///
+/// EFI_IP6_VARIABLE_DATA is deprecated in the UEFI 2.4B and should not be used any more.
+/// The definition in here is only present to provide backwards compatability.
+///
+typedef struct {
+ ///
+ /// The handle of the driver that creates this entry.
+ ///
+ EFI_HANDLE DriverHandle;
+ ///
+ /// The number of IPv6 address pairs that follow this data structure.
+ ///
+ UINT32 AddressCount;
+ ///
+ /// List of IPv6 address pairs that are currently in use.
+ ///
+ EFI_IP6_ADDRESS_PAIR AddressPairs[1];
+} EFI_IP6_VARIABLE_DATA;
+
+///
+/// ICMPv6 type definitions for error messages
+///
+///@{
+#define ICMP_V6_DEST_UNREACHABLE 0x1
+#define ICMP_V6_PACKET_TOO_BIG 0x2
+#define ICMP_V6_TIME_EXCEEDED 0x3
+#define ICMP_V6_PARAMETER_PROBLEM 0x4
+///@}
+
+///
+/// ICMPv6 type definition for informational messages
+///
+///@{
+#define ICMP_V6_ECHO_REQUEST 0x80
+#define ICMP_V6_ECHO_REPLY 0x81
+#define ICMP_V6_LISTENER_QUERY 0x82
+#define ICMP_V6_LISTENER_REPORT 0x83
+#define ICMP_V6_LISTENER_DONE 0x84
+#define ICMP_V6_ROUTER_SOLICIT 0x85
+#define ICMP_V6_ROUTER_ADVERTISE 0x86
+#define ICMP_V6_NEIGHBOR_SOLICIT 0x87
+#define ICMP_V6_NEIGHBOR_ADVERTISE 0x88
+#define ICMP_V6_REDIRECT 0x89
+#define ICMP_V6_LISTENER_REPORT_2 0x8F
+///@}
+
+///
+/// ICMPv6 code definitions for ICMP_V6_DEST_UNREACHABLE
+///
+///@{
+#define ICMP_V6_NO_ROUTE_TO_DEST 0x0
+#define ICMP_V6_COMM_PROHIBITED 0x1
+#define ICMP_V6_BEYOND_SCOPE 0x2
+#define ICMP_V6_ADDR_UNREACHABLE 0x3
+#define ICMP_V6_PORT_UNREACHABLE 0x4
+#define ICMP_V6_SOURCE_ADDR_FAILED 0x5
+#define ICMP_V6_ROUTE_REJECTED 0x6
+///@}
+
+///
+/// ICMPv6 code definitions for ICMP_V6_TIME_EXCEEDED
+///
+///@{
+#define ICMP_V6_TIMEOUT_HOP_LIMIT 0x0
+#define ICMP_V6_TIMEOUT_REASSEMBLE 0x1
+///@}
+
+///
+/// ICMPv6 code definitions for ICMP_V6_PARAMETER_PROBLEM
+///
+///@{
+#define ICMP_V6_ERRONEOUS_HEADER 0x0
+#define ICMP_V6_UNRECOGNIZE_NEXT_HDR 0x1
+#define ICMP_V6_UNRECOGNIZE_OPTION 0x2
+///@}
+
+///
+/// EFI_IP6_CONFIG_DATA
+/// is used to report and change IPv6 session parameters.
+///
+typedef struct {
+ ///
+ /// For the IPv6 packet to send and receive, this is the default value
+ /// of the 'Next Header' field in the last IPv6 extension header or in
+ /// the IPv6 header if there are no extension headers. Ignored when
+ /// AcceptPromiscuous is TRUE.
+ ///
+ UINT8 DefaultProtocol;
+ ///
+ /// Set to TRUE to receive all IPv6 packets that get through the
+ /// receive filters.
+ /// Set to FALSE to receive only the DefaultProtocol IPv6
+ /// packets that get through the receive filters. Ignored when
+ /// AcceptPromiscuous is TRUE.
+ ///
+ BOOLEAN AcceptAnyProtocol;
+ ///
+ /// Set to TRUE to receive ICMP error report packets. Ignored when
+ /// AcceptPromiscuous or AcceptAnyProtocol is TRUE.
+ ///
+ BOOLEAN AcceptIcmpErrors;
+ ///
+ /// Set to TRUE to receive all IPv6 packets that are sent to any
+ /// hardware address or any protocol address. Set to FALSE to stop
+ /// receiving all promiscuous IPv6 packets.
+ ///
+ BOOLEAN AcceptPromiscuous;
+ ///
+ /// The destination address of the packets that will be transmitted.
+ /// Ignored if it is unspecified.
+ ///
+ EFI_IPv6_ADDRESS DestinationAddress;
+ ///
+ /// The station IPv6 address that will be assigned to this EFI IPv6
+ /// Protocol instance. This field can be set and changed only when
+ /// the EFI IPv6 driver is transitioning from the stopped to the started
+ /// states. If the StationAddress is specified, the EFI IPv6 Protocol
+ /// driver will deliver only incoming IPv6 packets whose destination
+ /// matches this IPv6 address exactly. The StationAddress is required
+ /// to be one of currently configured IPv6 addresses. An address
+ /// containing all zeroes is also accepted as a special case. Under this
+ /// situation, the IPv6 driver is responsible for binding a source
+ /// address to this EFI IPv6 protocol instance according to the source
+ /// address selection algorithm. Only incoming packets destined to
+ /// the selected address will be delivered to the user. And the
+ /// selected station address can be retrieved through later
+ /// GetModeData() call. If no address is available for selecting,
+ /// EFI_NO_MAPPING will be returned, and the station address will
+ /// only be successfully bound to this EFI IPv6 protocol instance
+ /// after IP6ModeData.IsConfigured changed to TRUE.
+ ///
+ EFI_IPv6_ADDRESS StationAddress;
+ ///
+ /// TrafficClass field in transmitted IPv6 packets. Default value
+ /// is zero.
+ ///
+ UINT8 TrafficClass;
+ ///
+ /// HopLimit field in transmitted IPv6 packets.
+ ///
+ UINT8 HopLimit;
+ ///
+ /// FlowLabel field in transmitted IPv6 packets. Default value is
+ /// zero.
+ ///
+ UINT32 FlowLabel;
+ ///
+ /// The timer timeout value (number of microseconds) for the
+ /// receive timeout event to be associated with each assembled
+ /// packet. Zero means do not drop assembled packets.
+ ///
+ UINT32 ReceiveTimeout;
+ ///
+ /// The timer timeout value (number of microseconds) for the
+ /// transmit timeout event to be associated with each outgoing
+ /// packet. Zero means do not drop outgoing packets.
+ ///
+ UINT32 TransmitTimeout;
+} EFI_IP6_CONFIG_DATA;
+
+///
+/// EFI_IP6_ADDRESS_INFO
+///
+typedef struct {
+ EFI_IPv6_ADDRESS Address; ///< The IPv6 address.
+ UINT8 PrefixLength; ///< The length of the prefix associated with the Address.
+} EFI_IP6_ADDRESS_INFO;
+
+///
+/// EFI_IP6_ROUTE_TABLE
+/// is the entry structure that is used in routing tables
+///
+typedef struct {
+ ///
+ /// The IPv6 address of the gateway to be used as the next hop for
+ /// packets to this prefix. If the IPv6 address is all zeros, then the
+ /// prefix is on-link.
+ ///
+ EFI_IPv6_ADDRESS Gateway;
+ ///
+ /// The destination prefix to be routed.
+ ///
+ EFI_IPv6_ADDRESS Destination;
+ ///
+ /// The length of the prefix associated with the Destination.
+ ///
+ UINT8 PrefixLength;
+} EFI_IP6_ROUTE_TABLE;
+
+///
+/// EFI_IP6_NEIGHBOR_STATE
+///
+typedef enum {
+ ///
+ /// Address resolution is being performed on this entry. Specially,
+ /// Neighbor Solicitation has been sent to the solicited-node
+ /// multicast address of the target, but corresponding Neighbor
+ /// Advertisement has not been received.
+ ///
+ EfiNeighborInComplete,
+ ///
+ /// Positive confirmation was received that the forward path to the
+ /// neighbor was functioning properly.
+ ///
+ EfiNeighborReachable,
+ ///
+ /// Reachable Time has elapsed since the last positive confirmation
+ /// was received. In this state, the forward path to the neighbor was
+ /// functioning properly.
+ ///
+ EfiNeighborStale,
+ ///
+ /// This state is an optimization that gives upper-layer protocols
+ /// additional time to provide reachability confirmation.
+ ///
+ EfiNeighborDelay,
+ ///
+ /// A reachability confirmation is actively sought by retransmitting
+ /// Neighbor Solicitations every RetransTimer milliseconds until a
+ /// reachability confirmation is received.
+ ///
+ EfiNeighborProbe
+} EFI_IP6_NEIGHBOR_STATE;
+
+///
+/// EFI_IP6_NEIGHBOR_CACHE
+/// is the entry structure that is used in neighbor cache. It records a set
+/// of entries about individual neighbors to which traffic has been sent recently.
+///
+typedef struct {
+ EFI_IPv6_ADDRESS Neighbor; ///< The on-link unicast/anycast IP address of the neighbor.
+ EFI_MAC_ADDRESS LinkAddress; ///< Link-layer address of the neighbor.
+ EFI_IP6_NEIGHBOR_STATE State; ///< State of this neighbor cache entry.
+} EFI_IP6_NEIGHBOR_CACHE;
+
+///
+/// EFI_IP6_ICMP_TYPE
+/// is used to describe those ICMP messages that are supported by this EFI
+/// IPv6 Protocol driver.
+///
+typedef struct {
+ UINT8 Type; ///< The type of ICMP message.
+ UINT8 Code; ///< The code of the ICMP message.
+} EFI_IP6_ICMP_TYPE;
+
+///
+/// EFI_IP6_MODE_DATA
+///
+typedef struct {
+ ///
+ /// Set to TRUE after this EFI IPv6 Protocol instance is started.
+ /// All other fields in this structure are undefined until this field is TRUE.
+ /// Set to FALSE when the EFI IPv6 Protocol instance is stopped.
+ ///
+ BOOLEAN IsStarted;
+ ///
+ /// The maximum packet size, in bytes, of the packet which the upper layer driver could feed.
+ ///
+ UINT32 MaxPacketSize;
+ ///
+ /// Current configuration settings. Undefined until IsStarted is TRUE.
+ ///
+ EFI_IP6_CONFIG_DATA ConfigData;
+ ///
+ /// Set to TRUE when the EFI IPv6 Protocol instance is configured.
+ /// The instance is configured when it has a station address and
+ /// corresponding prefix length.
+ /// Set to FALSE when the EFI IPv6 Protocol instance is not configured.
+ ///
+ BOOLEAN IsConfigured;
+ ///
+ /// Number of configured IPv6 addresses on this interface.
+ ///
+ UINT32 AddressCount;
+ ///
+ /// List of currently configured IPv6 addresses and corresponding
+ /// prefix lengths assigned to this interface. It is caller's
+ /// responsibility to free this buffer.
+ ///
+ EFI_IP6_ADDRESS_INFO *AddressList;
+ ///
+ /// Number of joined multicast groups. Undefined until
+ /// IsConfigured is TRUE.
+ ///
+ UINT32 GroupCount;
+ ///
+ /// List of joined multicast group addresses. It is caller's
+ /// responsibility to free this buffer. Undefined until
+ /// IsConfigured is TRUE.
+ ///
+ EFI_IPv6_ADDRESS *GroupTable;
+ ///
+ /// Number of entries in the routing table. Undefined until
+ /// IsConfigured is TRUE.
+ ///
+ UINT32 RouteCount;
+ ///
+ /// Routing table entries. It is caller's responsibility to free this buffer.
+ ///
+ EFI_IP6_ROUTE_TABLE *RouteTable;
+ ///
+ /// Number of entries in the neighbor cache. Undefined until
+ /// IsConfigured is TRUE.
+ ///
+ UINT32 NeighborCount;
+ ///
+ /// Neighbor cache entries. It is caller's responsibility to free this
+ /// buffer. Undefined until IsConfigured is TRUE.
+ ///
+ EFI_IP6_NEIGHBOR_CACHE *NeighborCache;
+ ///
+ /// Number of entries in the prefix table. Undefined until
+ /// IsConfigured is TRUE.
+ ///
+ UINT32 PrefixCount;
+ ///
+ /// On-link Prefix table entries. It is caller's responsibility to free this
+ /// buffer. Undefined until IsConfigured is TRUE.
+ ///
+ EFI_IP6_ADDRESS_INFO *PrefixTable;
+ ///
+ /// Number of entries in the supported ICMP types list.
+ ///
+ UINT32 IcmpTypeCount;
+ ///
+ /// Array of ICMP types and codes that are supported by this EFI
+ /// IPv6 Protocol driver. It is caller's responsibility to free this
+ /// buffer.
+ ///
+ EFI_IP6_ICMP_TYPE *IcmpTypeList;
+} EFI_IP6_MODE_DATA;
+
+///
+/// EFI_IP6_HEADER
+/// The fields in the IPv6 header structure are defined in the Internet
+/// Protocol version6 specification.
+///
+#pragma pack(1)
+typedef struct _EFI_IP6_HEADER {
+ UINT8 TrafficClassH : 4;
+ UINT8 Version : 4;
+ UINT8 FlowLabelH : 4;
+ UINT8 TrafficClassL : 4;
+ UINT16 FlowLabelL;
+ UINT16 PayloadLength;
+ UINT8 NextHeader;
+ UINT8 HopLimit;
+ EFI_IPv6_ADDRESS SourceAddress;
+ EFI_IPv6_ADDRESS DestinationAddress;
+} EFI_IP6_HEADER;
+#pragma pack()
+
+///
+/// EFI_IP6_FRAGMENT_DATA
+/// describes the location and length of the IPv6 packet
+/// fragment to transmit or that has been received.
+///
+typedef struct _EFI_IP6_FRAGMENT_DATA {
+ UINT32 FragmentLength; ///< Length of fragment data. This field may not be set to zero.
+ VOID *FragmentBuffer; ///< Pointer to fragment data. This field may not be set to NULL.
+} EFI_IP6_FRAGMENT_DATA;
+
+///
+/// EFI_IP6_RECEIVE_DATA
+///
+typedef struct _EFI_IP6_RECEIVE_DATA {
+ ///
+ /// Time when the EFI IPv6 Protocol driver accepted the packet.
+ /// Ignored if it is zero.
+ ///
+ EFI_TIME TimeStamp;
+ ///
+ /// After this event is signaled, the receive data structure is released
+ /// and must not be referenced.
+ ///
+ EFI_EVENT RecycleSignal;
+ ///
+ /// Length of the IPv6 packet headers, including both the IPv6
+ /// header and any extension headers.
+ ///
+ UINT32 HeaderLength;
+ ///
+ /// Pointer to the IPv6 packet header. If the IPv6 packet was
+ /// fragmented, this argument is a pointer to the header in the first
+ /// fragment.
+ ///
+ EFI_IP6_HEADER *Header;
+ ///
+ /// Sum of the lengths of IPv6 packet buffers in FragmentTable. May
+ /// be zero.
+ ///
+ UINT32 DataLength;
+ ///
+ /// Number of IPv6 payload fragments. May be zero.
+ ///
+ UINT32 FragmentCount;
+ ///
+ /// Array of payload fragment lengths and buffer pointers.
+ ///
+ EFI_IP6_FRAGMENT_DATA FragmentTable[1];
+} EFI_IP6_RECEIVE_DATA;
+
+///
+/// EFI_IP6_OVERRIDE_DATA
+/// The information and flags in the override data structure will override
+/// default parameters or settings for one Transmit() function call.
+///
+typedef struct _EFI_IP6_OVERRIDE_DATA {
+ UINT8 Protocol; ///< Protocol type override.
+ UINT8 HopLimit; ///< Hop-Limit override.
+ UINT32 FlowLabel; ///< Flow-Label override.
+} EFI_IP6_OVERRIDE_DATA;
+
+///
+/// EFI_IP6_TRANSMIT_DATA
+///
+typedef struct _EFI_IP6_TRANSMIT_DATA {
+ ///
+ /// The destination IPv6 address. If it is unspecified,
+ /// ConfigData.DestinationAddress will be used instead.
+ ///
+ EFI_IPv6_ADDRESS DestinationAddress;
+ ///
+ /// If not NULL, the IPv6 transmission control override data.
+ ///
+ EFI_IP6_OVERRIDE_DATA *OverrideData;
+ ///
+ /// Total length in byte of the IPv6 extension headers specified in
+ /// ExtHdrs.
+ ///
+ UINT32 ExtHdrsLength;
+ ///
+ /// Pointer to the IPv6 extension headers. The IP layer will append
+ /// the required extension headers if they are not specified by
+ /// ExtHdrs. Ignored if ExtHdrsLength is zero.
+ ///
+ VOID *ExtHdrs;
+ ///
+ /// The protocol of first extension header in ExtHdrs. Ignored if
+ /// ExtHdrsLength is zero.
+ ///
+ UINT8 NextHeader;
+ ///
+ /// Total length in bytes of the FragmentTable data to transmit.
+ ///
+ UINT32 DataLength;
+ ///
+ /// Number of entries in the fragment data table.
+ ///
+ UINT32 FragmentCount;
+ ///
+ /// Start of the fragment data table.
+ ///
+ EFI_IP6_FRAGMENT_DATA FragmentTable[1];
+} EFI_IP6_TRANSMIT_DATA;
+
+///
+/// EFI_IP6_COMPLETION_TOKEN
+/// structures are used for both transmit and receive operations.
+///
+typedef struct {
+ ///
+ /// This Event will be signaled after the Status field is updated by
+ /// the EFI IPv6 Protocol driver. The type of Event must be EFI_NOTIFY_SIGNAL.
+ ///
+ EFI_EVENT Event;
+ ///
+ /// Will be set to one of the following values:
+ /// - EFI_SUCCESS: The receive or transmit completed
+ /// successfully.
+ /// - EFI_ABORTED: The receive or transmit was aborted
+ /// - EFI_TIMEOUT: The transmit timeout expired.
+ /// - EFI_ICMP_ERROR: An ICMP error packet was received.
+ /// - EFI_DEVICE_ERROR: An unexpected system or network
+ /// error occurred.
+ /// - EFI_SECURITY_VIOLATION: The transmit or receive was
+ /// failed because of an IPsec policy check.
+ /// - EFI_NO_MEDIA: There was a media error.
+ ///
+ EFI_STATUS Status;
+ union {
+ ///
+ /// When the Token is used for receiving, RxData is a pointer to the EFI_IP6_RECEIVE_DATA.
+ ///
+ EFI_IP6_RECEIVE_DATA *RxData;
+ ///
+ /// When the Token is used for transmitting, TxData is a pointer to the EFI_IP6_TRANSMIT_DATA.
+ ///
+ EFI_IP6_TRANSMIT_DATA *TxData;
+ } Packet;
+} EFI_IP6_COMPLETION_TOKEN;
+
+/**
+ Gets the current operational settings for this instance of the EFI IPv6 Protocol driver.
+
+ The GetModeData() function returns the current operational mode data for this driver instance.
+ The data fields in EFI_IP6_MODE_DATA are read only. This function is used optionally to
+ retrieve the operational mode data of underlying networks or drivers..
+
+ @param[in] This Pointer to the EFI_IP6_PROTOCOL instance.
+ @param[out] Ip6ModeData Pointer to the EFI IPv6 Protocol mode data structure.
+ @param[out] MnpConfigData Pointer to the managed network configuration data structure.
+ @param[out] SnpModeData Pointer to the simple network mode data structure.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_OUT_OF_RESOURCES The required mode data could not be allocated.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP6_GET_MODE_DATA)(
+ IN EFI_IP6_PROTOCOL *This,
+ OUT EFI_IP6_MODE_DATA *Ip6ModeData OPTIONAL,
+ OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL,
+ OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL
+ );
+
+/**
+ Assigns an IPv6 address and subnet mask to this EFI IPv6 Protocol driver instance.
+
+ The Configure() function is used to set, change, or reset the operational parameters and filter
+ settings for this EFI IPv6 Protocol instance. Until these parameters have been set, no network traffic
+ can be sent or received by this instance. Once the parameters have been reset (by calling this
+ function with Ip6ConfigData set to NULL), no more traffic can be sent or received until these
+ parameters have been set again. Each EFI IPv6 Protocol instance can be started and stopped
+ independently of each other by enabling or disabling their receive filter settings with the
+ Configure() function.
+
+ If Ip6ConfigData.StationAddress is a valid non-zero IPv6 unicast address, it is required
+ to be one of the currently configured IPv6 addresses list in the EFI IPv6 drivers, or else
+ EFI_INVALID_PARAMETER will be returned. If Ip6ConfigData.StationAddress is
+ unspecified, the IPv6 driver will bind a source address according to the source address selection
+ algorithm. Clients could frequently call GetModeData() to check get currently configured IPv6
+ address list in the EFI IPv6 driver. If both Ip6ConfigData.StationAddress and
+ Ip6ConfigData.Destination are unspecified, when transmitting the packet afterwards, the
+ source address filled in each outgoing IPv6 packet is decided based on the destination of this packet. .
+
+ If operational parameters are reset or changed, any pending transmit and receive requests will be
+ cancelled. Their completion token status will be set to EFI_ABORTED and their events will be
+ signaled.
+
+ @param[in] This Pointer to the EFI_IP6_PROTOCOL instance.
+ @param[in] Ip6ConfigData Pointer to the EFI IPv6 Protocol configuration data structure.
+
+ @retval EFI_SUCCESS The driver instance was successfully opened.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ - This is NULL.
+ - Ip6ConfigData.StationAddress is neither zero nor
+ a unicast IPv6 address.
+ - Ip6ConfigData.StationAddress is neither zero nor
+ one of the configured IP addresses in the EFI IPv6 driver.
+ - Ip6ConfigData.DefaultProtocol is illegal.
+ @retval EFI_OUT_OF_RESOURCES The EFI IPv6 Protocol driver instance data could not be allocated.
+ @retval EFI_NO_MAPPING The IPv6 driver was responsible for choosing a source address for
+ this instance, but no source address was available for use.
+ @retval EFI_ALREADY_STARTED The interface is already open and must be stopped before the IPv6
+ address or prefix length can be changed.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI IPv6
+ Protocol driver instance is not opened.
+ @retval EFI_UNSUPPORTED Default protocol specified through
+ Ip6ConfigData.DefaulProtocol isn't supported.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP6_CONFIGURE)(
+ IN EFI_IP6_PROTOCOL *This,
+ IN EFI_IP6_CONFIG_DATA *Ip6ConfigData OPTIONAL
+ );
+
+/**
+ Joins and leaves multicast groups.
+
+ The Groups() function is used to join and leave multicast group sessions. Joining a group will
+ enable reception of matching multicast packets. Leaving a group will disable reception of matching
+ multicast packets. Source-Specific Multicast isn't required to be supported.
+
+ If JoinFlag is FALSE and GroupAddress is NULL, all joined groups will be left.
+
+ @param[in] This Pointer to the EFI_IP6_PROTOCOL instance.
+ @param[in] JoinFlag Set to TRUE to join the multicast group session and FALSE to leave.
+ @param[in] GroupAddress Pointer to the IPv6 multicast address.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the following is TRUE:
+ - This is NULL.
+ - JoinFlag is TRUE and GroupAddress is NULL.
+ - GroupAddress is not NULL and *GroupAddress is
+ not a multicast IPv6 address.
+ - GroupAddress is not NULL and *GroupAddress is in the
+ range of SSM destination address.
+ @retval EFI_NOT_STARTED This instance has not been started.
+ @retval EFI_OUT_OF_RESOURCES System resources could not be allocated.
+ @retval EFI_UNSUPPORTED This EFI IPv6 Protocol implementation does not support multicast groups.
+ @retval EFI_ALREADY_STARTED The group address is already in the group table (when
+ JoinFlag is TRUE).
+ @retval EFI_NOT_FOUND The group address is not in the group table (when JoinFlag is FALSE).
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP6_GROUPS)(
+ IN EFI_IP6_PROTOCOL *This,
+ IN BOOLEAN JoinFlag,
+ IN EFI_IPv6_ADDRESS *GroupAddress OPTIONAL
+ );
+
+/**
+ Adds and deletes routing table entries.
+
+ The Routes() function adds a route to or deletes a route from the routing table.
+
+ Routes are determined by comparing the leftmost PrefixLength bits of Destination with
+ the destination IPv6 address arithmetically. The gateway address must be on the same subnet as the
+ configured station address.
+
+ The default route is added with Destination and PrefixLegth both set to all zeros. The
+ default route matches all destination IPv6 addresses that do not match any other routes.
+
+ All EFI IPv6 Protocol instances share a routing table.
+
+ @param[in] This Pointer to the EFI_IP6_PROTOCOL instance.
+ @param[in] DeleteRoute Set to TRUE to delete this route from the routing table. Set to
+ FALSE to add this route to the routing table. Destination,
+ PrefixLength and Gateway are used as the key to each
+ route entry.
+ @param[in] Destination The address prefix of the subnet that needs to be routed.
+ @param[in] PrefixLength The prefix length of Destination. Ignored if Destination
+ is NULL.
+ @param[in] GatewayAddress The unicast gateway IPv6 address for this route.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_NOT_STARTED The driver instance has not been started.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ - This is NULL.
+ - When DeleteRoute is TRUE, both Destination and
+ GatewayAddress are NULL.
+ - When DeleteRoute is FALSE, either Destination or
+ GatewayAddress is NULL.
+ - *GatewayAddress is not a valid unicast IPv6 address.
+ - *GatewayAddress is one of the local configured IPv6
+ addresses.
+ @retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table.
+ @retval EFI_NOT_FOUND This route is not in the routing table (when DeleteRoute is TRUE).
+ @retval EFI_ACCESS_DENIED The route is already defined in the routing table (when
+ DeleteRoute is FALSE).
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP6_ROUTES)(
+ IN EFI_IP6_PROTOCOL *This,
+ IN BOOLEAN DeleteRoute,
+ IN EFI_IPv6_ADDRESS *Destination OPTIONAL,
+ IN UINT8 PrefixLength,
+ IN EFI_IPv6_ADDRESS *GatewayAddress OPTIONAL
+ );
+
+/**
+ Add or delete Neighbor cache entries.
+
+ The Neighbors() function is used to add, update, or delete an entry from neighbor cache.
+ IPv6 neighbor cache entries are typically inserted and updated by the network protocol driver as
+ network traffic is processed. Most neighbor cache entries will time out and be deleted if the network
+ traffic stops. Neighbor cache entries that were inserted by Neighbors() may be static (will not
+ timeout) or dynamic (will time out).
+
+ The implementation should follow the neighbor cache timeout mechanism which is defined in
+ RFC4861. The default neighbor cache timeout value should be tuned for the expected network
+ environment
+
+ @param[in] This Pointer to the EFI_IP6_PROTOCOL instance.
+ @param[in] DeleteFlag Set to TRUE to delete the specified cache entry, set to FALSE to
+ add (or update, if it already exists and Override is TRUE) the
+ specified cache entry. TargetIp6Address is used as the key
+ to find the requested cache entry.
+ @param[in] TargetIp6Address Pointer to Target IPv6 address.
+ @param[in] TargetLinkAddress Pointer to link-layer address of the target. Ignored if NULL.
+ @param[in] Timeout Time in 100-ns units that this entry will remain in the neighbor
+ cache, it will be deleted after Timeout. A value of zero means that
+ the entry is permanent. A non-zero value means that the entry is
+ dynamic.
+ @param[in] Override If TRUE, the cached link-layer address of the matching entry will
+ be overridden and updated; if FALSE, EFI_ACCESS_DENIED
+ will be returned if a corresponding cache entry already existed.
+
+ @retval EFI_SUCCESS The data has been queued for transmission.
+ @retval EFI_NOT_STARTED This instance has not been started.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ - This is NULL.
+ - TargetIpAddress is NULL.
+ - *TargetLinkAddress is invalid when not NULL.
+ - *TargetIpAddress is not a valid unicast IPv6 address.
+ - *TargetIpAddress is one of the local configured IPv6
+ addresses.
+ @retval EFI_OUT_OF_RESOURCES Could not add the entry to the neighbor cache.
+ @retval EFI_NOT_FOUND This entry is not in the neighbor cache (when DeleteFlag is
+ TRUE or when DeleteFlag is FALSE while
+ TargetLinkAddress is NULL.).
+ @retval EFI_ACCESS_DENIED The to-be-added entry is already defined in the neighbor cache,
+ and that entry is tagged as un-overridden (when DeleteFlag
+ is FALSE).
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP6_NEIGHBORS)(
+ IN EFI_IP6_PROTOCOL *This,
+ IN BOOLEAN DeleteFlag,
+ IN EFI_IPv6_ADDRESS *TargetIp6Address,
+ IN EFI_MAC_ADDRESS *TargetLinkAddress,
+ IN UINT32 Timeout,
+ IN BOOLEAN Override
+ );
+
+/**
+ Places outgoing data packets into the transmit queue.
+
+ The Transmit() function places a sending request in the transmit queue of this
+ EFI IPv6 Protocol instance. Whenever the packet in the token is sent out or some
+ errors occur, the event in the token will be signaled and the status is updated.
+
+ @param[in] This Pointer to the EFI_IP6_PROTOCOL instance.
+ @param[in] Token Pointer to the transmit token.
+
+ @retval EFI_SUCCESS The data has been queued for transmission.
+ @retval EFI_NOT_STARTED This instance has not been started.
+ @retval EFI_NO_MAPPING The IPv6 driver was responsible for choosing a source address for
+ this transmission, but no source address was available for use.
+ @retval EFI_INVALID_PARAMETER One or more of the following is TRUE:
+ - This is NULL.
+ - Token is NULL.
+ - Token.Event is NULL.
+ - Token.Packet.TxData is NULL.
+ - Token.Packet.ExtHdrsLength is not zero and Token.Packet.ExtHdrs is NULL.
+ - Token.Packet.FragmentCount is zero.
+ - One or more of the Token.Packet.TxData.FragmentTable[].FragmentLength fields is zero.
+ - One or more of the Token.Packet.TxData.FragmentTable[].FragmentBuffer fields is NULL.
+ - Token.Packet.TxData.DataLength is zero or not equal to the sum of fragment lengths.
+ - Token.Packet.TxData.DestinationAddress is non-zero when DestinationAddress is configured as
+ non-zero when doing Configure() for this EFI IPv6 protocol instance.
+ - Token.Packet.TxData.DestinationAddress is unspecified when DestinationAddress is unspecified
+ when doing Configure() for this EFI IPv6 protocol instance.
+ @retval EFI_ACCESS_DENIED The transmit completion token with the same Token.Event
+ was already in the transmit queue.
+ @retval EFI_NOT_READY The completion token could not be queued because the transmit
+ queue is full.
+ @retval EFI_NOT_FOUND Not route is found to destination address.
+ @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data.
+ @retval EFI_BUFFER_TOO_SMALL Token.Packet.TxData.TotalDataLength is too
+ short to transmit.
+ @retval EFI_BAD_BUFFER_SIZE If Token.Packet.TxData.DataLength is beyond the
+ maximum that which can be described through the Fragment Offset
+ field in Fragment header when performing fragmentation.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP6_TRANSMIT)(
+ IN EFI_IP6_PROTOCOL *This,
+ IN EFI_IP6_COMPLETION_TOKEN *Token
+ );
+
+/**
+ Places a receiving request into the receiving queue.
+
+ The Receive() function places a completion token into the receive packet queue.
+ This function is always asynchronous.
+
+ The Token.Event field in the completion token must be filled in by the caller
+ and cannot be NULL. When the receive operation completes, the EFI IPv6 Protocol
+ driver updates the Token.Status and Token.Packet.RxData fields and the Token.Event
+ is signaled.
+
+ @param[in] This Pointer to the EFI_IP6_PROTOCOL instance.
+ @param[in] Token Pointer to a token that is associated with the receive data descriptor.
+
+ @retval EFI_SUCCESS The receive completion token was cached.
+ @retval EFI_NOT_STARTED This EFI IPv6 Protocol instance has not been started.
+ @retval EFI_NO_MAPPING When IP6 driver responsible for binding source address to this instance,
+ while no source address is available for use.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ - This is NULL.
+ - Token is NULL.
+ - Token.Event is NULL.
+ @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued due to a lack of system
+ resources (usually memory).
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ The EFI IPv6 Protocol instance has been reset to startup defaults.
+ @retval EFI_ACCESS_DENIED The receive completion token with the same Token.Event was already
+ in the receive queue.
+ @retval EFI_NOT_READY The receive request could not be queued because the receive queue is full.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP6_RECEIVE)(
+ IN EFI_IP6_PROTOCOL *This,
+ IN EFI_IP6_COMPLETION_TOKEN *Token
+ );
+
+/**
+ Abort an asynchronous transmit or receive request.
+
+ The Cancel() function is used to abort a pending transmit or receive request.
+ If the token is in the transmit or receive request queues, after calling this
+ function, Token->Status will be set to EFI_ABORTED and then Token->Event will
+ be signaled. If the token is not in one of the queues, which usually means the
+ asynchronous operation has completed, this function will not signal the token
+ and EFI_NOT_FOUND is returned.
+
+ @param[in] This Pointer to the EFI_IP6_PROTOCOL instance.
+ @param[in] Token Pointer to a token that has been issued by
+ EFI_IP6_PROTOCOL.Transmit() or
+ EFI_IP6_PROTOCOL.Receive(). If NULL, all pending
+ tokens are aborted. Type EFI_IP6_COMPLETION_TOKEN is
+ defined in EFI_IP6_PROTOCOL.Transmit().
+
+ @retval EFI_SUCCESS The asynchronous I/O request was aborted and
+ Token->Event was signaled. When Token is NULL, all
+ pending requests were aborted and their events were signaled.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_NOT_STARTED This instance has not been started.
+ @retval EFI_NOT_FOUND When Token is not NULL, the asynchronous I/O request was
+ not found in the transmit or receive queue. It has either completed
+ or was not issued by Transmit() and Receive().
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP6_CANCEL)(
+ IN EFI_IP6_PROTOCOL *This,
+ IN EFI_IP6_COMPLETION_TOKEN *Token OPTIONAL
+ );
+
+/**
+ Polls for incoming data packets and processes outgoing data packets.
+
+ The Poll() function polls for incoming data packets and processes outgoing data
+ packets. Network drivers and applications can call the EFI_IP6_PROTOCOL.Poll()
+ function to increase the rate that data packets are moved between the communications
+ device and the transmit and receive queues.
+
+ In some systems the periodic timer event may not poll the underlying communications
+ device fast enough to transmit and/or receive all data packets without missing
+ incoming packets or dropping outgoing packets. Drivers and applications that are
+ experiencing packet loss should try calling the EFI_IP6_PROTOCOL.Poll() function
+ more often.
+
+ @param[in] This Pointer to the EFI_IP6_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Incoming or outgoing data was processed.
+ @retval EFI_NOT_STARTED This EFI IPv6 Protocol instance has not been started.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_NOT_READY No incoming or outgoing data is processed.
+ @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue.
+ Consider increasing the polling rate.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP6_POLL)(
+ IN EFI_IP6_PROTOCOL *This
+ );
+
+///
+/// The EFI IPv6 Protocol implements a simple packet-oriented interface that can be
+/// used by drivers, daemons, and applications to transmit and receive network packets.
+///
+struct _EFI_IP6_PROTOCOL {
+ EFI_IP6_GET_MODE_DATA GetModeData;
+ EFI_IP6_CONFIGURE Configure;
+ EFI_IP6_GROUPS Groups;
+ EFI_IP6_ROUTES Routes;
+ EFI_IP6_NEIGHBORS Neighbors;
+ EFI_IP6_TRANSMIT Transmit;
+ EFI_IP6_RECEIVE Receive;
+ EFI_IP6_CANCEL Cancel;
+ EFI_IP6_POLL Poll;
+};
+
+extern EFI_GUID gEfiIp6ServiceBindingProtocolGuid;
+extern EFI_GUID gEfiIp6ProtocolGuid;
+
+#endif
diff --git a/src/include/ipxe/efi/Protocol/Ip6Config.h b/src/include/ipxe/efi/Protocol/Ip6Config.h
new file mode 100644
index 00000000..5665e93b
--- /dev/null
+++ b/src/include/ipxe/efi/Protocol/Ip6Config.h
@@ -0,0 +1,369 @@
+/** @file
+ This file provides a definition of the EFI IPv6 Configuration
+ Protocol.
+
+Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __EFI_IP6CONFIG_PROTOCOL_H__
+#define __EFI_IP6CONFIG_PROTOCOL_H__
+
+FILE_LICENCE ( BSD2_PATENT );
+
+#include <ipxe/efi/Protocol/Ip6.h>
+
+#define EFI_IP6_CONFIG_PROTOCOL_GUID \
+ { \
+ 0x937fe521, 0x95ae, 0x4d1a, {0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } \
+ }
+
+typedef struct _EFI_IP6_CONFIG_PROTOCOL EFI_IP6_CONFIG_PROTOCOL;
+
+///
+/// EFI_IP6_CONFIG_DATA_TYPE
+///
+typedef enum {
+ ///
+ /// The interface information of the communication
+ /// device this EFI IPv6 Configuration Protocol instance manages.
+ /// This type of data is read only.The corresponding Data is of type
+ /// EFI_IP6_CONFIG_INTERFACE_INFO.
+ ///
+ Ip6ConfigDataTypeInterfaceInfo,
+ ///
+ /// The alternative interface ID for the
+ /// communication device this EFI IPv6 Configuration Protocol
+ /// instance manages if the link local IPv6 address generated from
+ /// the interfaced ID based on the default source the EFI IPv6
+ /// Protocol uses is a duplicate address. The length of the interface
+ /// ID is 64 bit. The corresponding Data is of type
+ /// EFI_IP6_CONFIG_INTERFACE_ID.
+ ///
+ Ip6ConfigDataTypeAltInterfaceId,
+ ///
+ /// The general configuration policy for the EFI IPv6 network
+ /// stack running on the communication device this EFI IPv6
+ /// Configuration Protocol instance manages. The policy will affect
+ /// other configuration settings. The corresponding Data is of type
+ /// EFI_IP6_CONFIG_POLICY.
+ ///
+ Ip6ConfigDataTypePolicy,
+ ///
+ /// The number of consecutive
+ /// Neighbor Solicitation messages sent while performing Duplicate
+ /// Address Detection on a tentative address. A value of zero
+ /// indicates that Duplicate Address Detection will not be performed
+ /// on tentative addresses. The corresponding Data is of type
+ /// EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS.
+ ///
+ Ip6ConfigDataTypeDupAddrDetectTransmits,
+ ///
+ /// The station addresses set manually for the EFI
+ /// IPv6 network stack. It is only configurable when the policy is
+ /// Ip6ConfigPolicyManual. The corresponding Data is a
+ /// pointer to an array of EFI_IPv6_ADDRESS instances. When
+ /// DataSize is 0 and Data is NULL, the existing configuration
+ /// is cleared from the EFI IPv6 Configuration Protocol instance.
+ ///
+ Ip6ConfigDataTypeManualAddress,
+ ///
+ /// The gateway addresses set manually for the EFI IPv6
+ /// network stack running on the communication device this EFI
+ /// IPv6 Configuration Protocol manages. It is not configurable when
+ /// the policy is Ip6ConfigPolicyAutomatic. The gateway
+ /// addresses must be unicast IPv6 addresses. The corresponding
+ /// Data is a pointer to an array of EFI_IPv6_ADDRESS instances.
+ /// When DataSize is 0 and Data is NULL, the existing configuration
+ /// is cleared from the EFI IPv6 Configuration Protocol instance.
+ ///
+ Ip6ConfigDataTypeGateway,
+ ///
+ /// The DNS server list for the EFI IPv6 network stack
+ /// running on the communication device this EFI IPv6
+ /// Configuration Protocol manages. It is not configurable when the
+ /// policy is Ip6ConfigPolicyAutomatic.The DNS server
+ /// addresses must be unicast IPv6 addresses. The corresponding
+ /// Data is a pointer to an array of EFI_IPv6_ADDRESS instances.
+ /// When DataSize is 0 and Data is NULL, the existing configuration
+ /// is cleared from the EFI IPv6 Configuration Protocol instance.
+ ///
+ Ip6ConfigDataTypeDnsServer,
+ ///
+ /// The number of this enumeration memebers.
+ ///
+ Ip6ConfigDataTypeMaximum
+} EFI_IP6_CONFIG_DATA_TYPE;
+
+///
+/// EFI_IP6_CONFIG_INTERFACE_INFO
+/// describes the operational state of the interface this
+/// EFI IPv6 Configuration Protocol instance manages.
+///
+typedef struct {
+ ///
+ /// The name of the interface. It is a NULL-terminated string.
+ ///
+ CHAR16 Name[32];
+ ///
+ /// The interface type of the network interface.
+ ///
+ UINT8 IfType;
+ ///
+ /// The size, in bytes, of the network interface's hardware address.
+ ///
+ UINT32 HwAddressSize;
+ ///
+ /// The hardware address for the network interface.
+ ///
+ EFI_MAC_ADDRESS HwAddress;
+ ///
+ /// Number of EFI_IP6_ADDRESS_INFO structures pointed to by AddressInfo.
+ ///
+ UINT32 AddressInfoCount;
+ ///
+ /// Pointer to an array of EFI_IP6_ADDRESS_INFO instances
+ /// which contain the local IPv6 addresses and the corresponding
+ /// prefix length information. Set to NULL if AddressInfoCount
+ /// is zero.
+ ///
+ EFI_IP6_ADDRESS_INFO *AddressInfo;
+ ///
+ /// Number of route table entries in the following RouteTable.
+ ///
+ UINT32 RouteCount;
+ ///
+ /// The route table of the IPv6 network stack runs on this interface.
+ /// Set to NULL if RouteCount is zero.
+ ///
+ EFI_IP6_ROUTE_TABLE *RouteTable;
+} EFI_IP6_CONFIG_INTERFACE_INFO;
+
+///
+/// EFI_IP6_CONFIG_INTERFACE_ID
+/// describes the 64-bit interface ID.
+///
+typedef struct {
+ UINT8 Id[8];
+} EFI_IP6_CONFIG_INTERFACE_ID;
+
+///
+/// EFI_IP6_CONFIG_POLICY
+/// defines the general configuration policy the EFI IPv6
+/// Configuration Protocol supports.
+///
+typedef enum {
+ ///
+ /// Under this policy, the IpI6ConfigDataTypeManualAddress,
+ /// Ip6ConfigDataTypeGateway and Ip6ConfigDataTypeDnsServer
+ /// configuration data are required to be set manually.
+ /// The EFI IPv6 Protocol will get all required configuration
+ /// such as address, prefix and gateway settings from the EFI
+ /// IPv6 Configuration protocol.
+ ///
+ Ip6ConfigPolicyManual,
+ ///
+ /// Under this policy, the IpI6ConfigDataTypeManualAddress,
+ /// Ip6ConfigDataTypeGateway and Ip6ConfigDataTypeDnsServer
+ /// configuration data are not allowed to set via SetData().
+ /// All of these configurations are retrieved from some auto
+ /// configuration mechanism.
+ /// The EFI IPv6 Protocol will use the IPv6 stateless address
+ /// autoconfiguration mechanism and/or the IPv6 stateful address
+ /// autoconfiguration mechanism described in the related RFCs to
+ /// get address and other configuration information
+ ///
+ Ip6ConfigPolicyAutomatic
+} EFI_IP6_CONFIG_POLICY;
+
+///
+/// EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS
+/// describes the number of consecutive Neighbor Solicitation messages sent
+/// while performing Duplicate Address Detection on a tentative address.
+/// The default value for a newly detected communication device is 1.
+///
+typedef struct {
+ UINT32 DupAddrDetectTransmits; ///< The number of consecutive Neighbor Solicitation messages sent.
+} EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS;
+
+///
+/// EFI_IP6_CONFIG_MANUAL_ADDRESS
+/// is used to set the station address information for the EFI IPv6 network
+/// stack manually when the policy is Ip6ConfigPolicyManual.
+///
+typedef struct {
+ EFI_IPv6_ADDRESS Address; ///< The IPv6 unicast address.
+ BOOLEAN IsAnycast; ///< Set to TRUE if Address is anycast.
+ UINT8 PrefixLength; ///< The length, in bits, of the prefix associated with this Address.
+} EFI_IP6_CONFIG_MANUAL_ADDRESS;
+
+/**
+ Set the configuration for the EFI IPv6 network stack running on the communication
+ device this EFI IPv6 Configuration Protocol instance manages.
+
+ This function is used to set the configuration data of type DataType for the EFI
+ IPv6 network stack running on the communication device this EFI IPv6 Configuration
+ Protocol instance manages.
+
+ The DataSize is used to calculate the count of structure instances in the Data for
+ some DataType that multiple structure instances are allowed.
+
+ This function is always non-blocking. When setting some type of configuration data,
+ an asynchronous process is invoked to check the correctness of the data, such as
+ doing Duplicate Address Detection on the manually set local IPv6 addresses.
+ EFI_NOT_READY is returned immediately to indicate that such an asynchronous process
+ is invoked and the process is not finished yet. The caller willing to get the result
+ of the asynchronous process is required to call RegisterDataNotify() to register an
+ event on the specified configuration data. Once the event is signaled, the caller
+ can call GetData() to get back the configuration data in order to know the result.
+ For other types of configuration data that do not require an asynchronous configuration
+ process, the result of the operation is immediately returned.
+
+ @param[in] This Pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
+ @param[in] DataType The type of data to set.
+ @param[in] DataSize Size of the buffer pointed to by Data in bytes.
+ @param[in] Data The data buffer to set. The type of the data buffer is
+ associated with the DataType.
+
+ @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
+ network stack is set successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
+ - This is NULL.
+ - One or more fields in Data and DataSize do not match the
+ requirement of the data type indicated by DataType.
+ @retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified
+ configuration data can not be set under the current policy
+ @retval EFI_ACCESS_DENIED Another set operation on the specified configuration
+ data is already in process.
+ @retval EFI_NOT_READY An asynchronous process is invoked to set the specified
+ configuration data and the process is not finished yet.
+ @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type
+ indicated by DataType.
+ @retval EFI_UNSUPPORTED This DataType is not supported.
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+ @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP6_CONFIG_SET_DATA)(
+ IN EFI_IP6_CONFIG_PROTOCOL *This,
+ IN EFI_IP6_CONFIG_DATA_TYPE DataType,
+ IN UINTN DataSize,
+ IN VOID *Data
+ );
+
+/**
+ Get the configuration data for the EFI IPv6 network stack running on the communication
+ device this EFI IPv6 Configuration Protocol instance manages.
+
+ This function returns the configuration data of type DataType for the EFI IPv6 network
+ stack running on the communication device this EFI IPv6 Configuration Protocol instance
+ manages.
+
+ The caller is responsible for allocating the buffer used to return the specified
+ configuration data and the required size will be returned to the caller if the size of
+ the buffer is too small.
+
+ EFI_NOT_READY is returned if the specified configuration data is not ready due to an
+ already in progress asynchronous configuration process. The caller can call RegisterDataNotify()
+ to register an event on the specified configuration data. Once the asynchronous configuration
+ process is finished, the event will be signaled and a subsequent GetData() call will return
+ the specified configuration data.
+
+ @param[in] This Pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
+ @param[in] DataType The type of data to get.
+ @param[in,out] DataSize On input, in bytes, the size of Data. On output, in bytes, the
+ size of buffer required to store the specified configuration data.
+ @param[in] Data The data buffer in which the configuration data is returned. The
+ type of the data buffer is associated with the DataType.
+
+ @retval EFI_SUCCESS The specified configuration data is got successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
+ - This is NULL.
+ - DataSize is NULL.
+ - Data is NULL if *DataSize is not zero.
+ @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified configuration data
+ and the required size is returned in DataSize.
+ @retval EFI_NOT_READY The specified configuration data is not ready due to an already in
+ progress asynchronous configuration process.
+ @retval EFI_NOT_FOUND The specified configuration data is not found.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP6_CONFIG_GET_DATA)(
+ IN EFI_IP6_CONFIG_PROTOCOL *This,
+ IN EFI_IP6_CONFIG_DATA_TYPE DataType,
+ IN OUT UINTN *DataSize,
+ IN VOID *Data OPTIONAL
+ );
+
+/**
+ Register an event that is to be signaled whenever a configuration process on the specified
+ configuration data is done.
+
+ This function registers an event that is to be signaled whenever a configuration process
+ on the specified configuration data is done. An event can be registered for different DataType
+ simultaneously and the caller is responsible for determining which type of configuration data
+ causes the signaling of the event in such case.
+
+ @param[in] This Pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
+ @param[in] DataType The type of data to unregister the event for.
+ @param[in] Event The event to register.
+
+ @retval EFI_SUCCESS The notification event for the specified configuration data is
+ registered.
+ @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
+ @retval EFI_UNSUPPORTED The configuration data type specified by DataType is not
+ supported.
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+ @retval EFI_ACCESS_DENIED The Event is already registered for the DataType.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP6_CONFIG_REGISTER_NOTIFY)(
+ IN EFI_IP6_CONFIG_PROTOCOL *This,
+ IN EFI_IP6_CONFIG_DATA_TYPE DataType,
+ IN EFI_EVENT Event
+ );
+
+/**
+ Remove a previously registered event for the specified configuration data.
+
+ This function removes a previously registered event for the specified configuration data.
+
+ @param[in] This Pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
+ @param[in] DataType The type of data to remove the previously registered event for.
+ @param[in] Event The event to unregister.
+
+ @retval EFI_SUCCESS The event registered for the specified configuration data is removed.
+ @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
+ @retval EFI_NOT_FOUND The Event has not been registered for the specified
+ DataType.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP6_CONFIG_UNREGISTER_NOTIFY)(
+ IN EFI_IP6_CONFIG_PROTOCOL *This,
+ IN EFI_IP6_CONFIG_DATA_TYPE DataType,
+ IN EFI_EVENT Event
+ );
+
+///
+/// The EFI_IP6_CONFIG_PROTOCOL provides the mechanism to set and get various
+/// types of configurations for the EFI IPv6 network stack.
+///
+struct _EFI_IP6_CONFIG_PROTOCOL {
+ EFI_IP6_CONFIG_SET_DATA SetData;
+ EFI_IP6_CONFIG_GET_DATA GetData;
+ EFI_IP6_CONFIG_REGISTER_NOTIFY RegisterDataNotify;
+ EFI_IP6_CONFIG_UNREGISTER_NOTIFY UnregisterDataNotify;
+};
+
+extern EFI_GUID gEfiIp6ConfigProtocolGuid;
+
+#endif
diff --git a/src/include/ipxe/efi/Protocol/Mtftp6.h b/src/include/ipxe/efi/Protocol/Mtftp6.h
new file mode 100644
index 00000000..b08af87e
--- /dev/null
+++ b/src/include/ipxe/efi/Protocol/Mtftp6.h
@@ -0,0 +1,820 @@
+/** @file
+ UEFI Multicast Trivial File Transfer Protocol v6 Definition, which is built upon
+ the EFI UDPv6 Protocol and provides basic services for client-side unicast and/or
+ multicast TFTP operations.
+
+ Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Revision Reference:
+ This Protocol is introduced in UEFI Specification 2.2
+
+**/
+
+#ifndef __EFI_MTFTP6_PROTOCOL_H__
+#define __EFI_MTFTP6_PROTOCOL_H__
+
+FILE_LICENCE ( BSD2_PATENT );
+
+#define EFI_MTFTP6_SERVICE_BINDING_PROTOCOL_GUID \
+ { \
+ 0xd9760ff3, 0x3cca, 0x4267, {0x80, 0xf9, 0x75, 0x27, 0xfa, 0xfa, 0x42, 0x23 } \
+ }
+
+#define EFI_MTFTP6_PROTOCOL_GUID \
+ { \
+ 0xbf0a78ba, 0xec29, 0x49cf, {0xa1, 0xc9, 0x7a, 0xe5, 0x4e, 0xab, 0x6a, 0x51 } \
+ }
+
+typedef struct _EFI_MTFTP6_PROTOCOL EFI_MTFTP6_PROTOCOL;
+typedef struct _EFI_MTFTP6_TOKEN EFI_MTFTP6_TOKEN;
+
+///
+/// MTFTP Packet OpCodes
+///@{
+#define EFI_MTFTP6_OPCODE_RRQ 1 ///< The MTFTPv6 packet is a read request.
+#define EFI_MTFTP6_OPCODE_WRQ 2 ///< The MTFTPv6 packet is a write request.
+#define EFI_MTFTP6_OPCODE_DATA 3 ///< The MTFTPv6 packet is a data packet.
+#define EFI_MTFTP6_OPCODE_ACK 4 ///< The MTFTPv6 packet is an acknowledgement packet.
+#define EFI_MTFTP6_OPCODE_ERROR 5 ///< The MTFTPv6 packet is an error packet.
+#define EFI_MTFTP6_OPCODE_OACK 6 ///< The MTFTPv6 packet is an option acknowledgement packet.
+#define EFI_MTFTP6_OPCODE_DIR 7 ///< The MTFTPv6 packet is a directory query packet.
+#define EFI_MTFTP6_OPCODE_DATA8 8 ///< The MTFTPv6 packet is a data packet with a big block number.
+#define EFI_MTFTP6_OPCODE_ACK8 9 ///< The MTFTPv6 packet is an acknowledgement packet with a big block number.
+///@}
+
+///
+/// MTFTP ERROR Packet ErrorCodes
+///@{
+///
+/// The error code is not defined. See the error message in the packet (if any) for details.
+///
+#define EFI_MTFTP6_ERRORCODE_NOT_DEFINED 0
+///
+/// The file was not found.
+///
+#define EFI_MTFTP6_ERRORCODE_FILE_NOT_FOUND 1
+///
+/// There was an access violation.
+///
+#define EFI_MTFTP6_ERRORCODE_ACCESS_VIOLATION 2
+///
+/// The disk was full or its allocation was exceeded.
+///
+#define EFI_MTFTP6_ERRORCODE_DISK_FULL 3
+///
+/// The MTFTPv6 operation was illegal.
+///
+#define EFI_MTFTP6_ERRORCODE_ILLEGAL_OPERATION 4
+///
+/// The transfer ID is unknown.
+///
+#define EFI_MTFTP6_ERRORCODE_UNKNOWN_TRANSFER_ID 5
+///
+/// The file already exists.
+///
+#define EFI_MTFTP6_ERRORCODE_FILE_ALREADY_EXISTS 6
+///
+/// There is no such user.
+///
+#define EFI_MTFTP6_ERRORCODE_NO_SUCH_USER 7
+///
+/// The request has been denied due to option negotiation.
+///
+#define EFI_MTFTP6_ERRORCODE_REQUEST_DENIED 8
+///@}
+
+#pragma pack(1)
+
+///
+/// EFI_MTFTP6_REQ_HEADER
+///
+typedef struct {
+ ///
+ /// For this packet type, OpCode = EFI_MTFTP6_OPCODE_RRQ for a read request
+ /// or OpCode = EFI_MTFTP6_OPCODE_WRQ for a write request.
+ ///
+ UINT16 OpCode;
+ ///
+ /// The file name to be downloaded or uploaded.
+ ///
+ UINT8 Filename[1];
+} EFI_MTFTP6_REQ_HEADER;
+
+///
+/// EFI_MTFTP6_OACK_HEADER
+///
+typedef struct {
+ ///
+ /// For this packet type, OpCode = EFI_MTFTP6_OPCODE_OACK.
+ ///
+ UINT16 OpCode;
+ ///
+ /// The option strings in the option acknowledgement packet.
+ ///
+ UINT8 Data[1];
+} EFI_MTFTP6_OACK_HEADER;
+
+///
+/// EFI_MTFTP6_DATA_HEADER
+///
+typedef struct {
+ ///
+ /// For this packet type, OpCode = EFI_MTFTP6_OPCODE_DATA.
+ ///
+ UINT16 OpCode;
+ ///
+ /// Block number of this data packet.
+ ///
+ UINT16 Block;
+ ///
+ /// The content of this data packet.
+ ///
+ UINT8 Data[1];
+} EFI_MTFTP6_DATA_HEADER;
+
+///
+/// EFI_MTFTP6_ACK_HEADER
+///
+typedef struct {
+ ///
+ /// For this packet type, OpCode = EFI_MTFTP6_OPCODE_ACK.
+ ///
+ UINT16 OpCode;
+ ///
+ /// The block number of the data packet that is being acknowledged.
+ ///
+ UINT16 Block[1];
+} EFI_MTFTP6_ACK_HEADER;
+
+///
+/// EFI_MTFTP6_DATA8_HEADER
+///
+typedef struct {
+ ///
+ /// For this packet type, OpCode = EFI_MTFTP6_OPCODE_DATA8.
+ ///
+ UINT16 OpCode;
+ ///
+ /// The block number of data packet.
+ ///
+ UINT64 Block;
+ ///
+ /// The content of this data packet.
+ ///
+ UINT8 Data[1];
+} EFI_MTFTP6_DATA8_HEADER;
+
+///
+/// EFI_MTFTP6_ACK8_HEADER
+///
+typedef struct {
+ ///
+ /// For this packet type, OpCode = EFI_MTFTP6_OPCODE_ACK8.
+ ///
+ UINT16 OpCode;
+ ///
+ /// The block number of the data packet that is being acknowledged.
+ ///
+ UINT64 Block[1];
+} EFI_MTFTP6_ACK8_HEADER;
+
+///
+/// EFI_MTFTP6_ERROR_HEADER
+///
+typedef struct {
+ ///
+ /// For this packet type, OpCode = EFI_MTFTP6_OPCODE_ERROR.
+ ///
+ UINT16 OpCode;
+ ///
+ /// The error number as defined by the MTFTPv6 packet error codes.
+ ///
+ UINT16 ErrorCode;
+ ///
+ /// Error message string.
+ ///
+ UINT8 ErrorMessage[1];
+} EFI_MTFTP6_ERROR_HEADER;
+
+///
+/// EFI_MTFTP6_PACKET
+///
+typedef union {
+ UINT16 OpCode; ///< Type of packets as defined by the MTFTPv6 packet opcodes.
+ EFI_MTFTP6_REQ_HEADER Rrq; ///< Read request packet header.
+ EFI_MTFTP6_REQ_HEADER Wrq; ///< write request packet header.
+ EFI_MTFTP6_OACK_HEADER Oack; ///< Option acknowledge packet header.
+ EFI_MTFTP6_DATA_HEADER Data; ///< Data packet header.
+ EFI_MTFTP6_ACK_HEADER Ack; ///< Acknowledgement packet header.
+ EFI_MTFTP6_DATA8_HEADER Data8; ///< Data packet header with big block number.
+ EFI_MTFTP6_ACK8_HEADER Ack8; ///< Acknowledgement header with big block number.
+ EFI_MTFTP6_ERROR_HEADER Error; ///< Error packet header.
+} EFI_MTFTP6_PACKET;
+
+#pragma pack()
+
+///
+/// EFI_MTFTP6_CONFIG_DATA
+///
+typedef struct {
+ ///
+ /// The local IP address to use. Set to zero to let the underlying IPv6
+ /// driver choose a source address. If not zero it must be one of the
+ /// configured IP addresses in the underlying IPv6 driver.
+ ///
+ EFI_IPv6_ADDRESS StationIp;
+ ///
+ /// Local port number. Set to zero to use the automatically assigned port number.
+ ///
+ UINT16 LocalPort;
+ ///
+ /// The IP address of the MTFTPv6 server.
+ ///
+ EFI_IPv6_ADDRESS ServerIp;
+ ///
+ /// The initial MTFTPv6 server port number. Request packets are
+ /// sent to this port. This number is almost always 69 and using zero
+ /// defaults to 69.
+ UINT16 InitialServerPort;
+ ///
+ /// The number of times to transmit MTFTPv6 request packets and wait for a response.
+ ///
+ UINT16 TryCount;
+ ///
+ /// The number of seconds to wait for a response after sending the MTFTPv6 request packet.
+ ///
+ UINT16 TimeoutValue;
+} EFI_MTFTP6_CONFIG_DATA;
+
+///
+/// EFI_MTFTP6_MODE_DATA
+///
+typedef struct {
+ ///
+ /// The configuration data of this instance.
+ ///
+ EFI_MTFTP6_CONFIG_DATA ConfigData;
+ ///
+ /// The number of option strings in the following SupportedOptions array.
+ ///
+ UINT8 SupportedOptionCount;
+ ///
+ /// An array of null-terminated ASCII option strings that are recognized and supported by
+ /// this EFI MTFTPv6 Protocol driver implementation. The buffer is
+ /// read only to the caller and the caller should NOT free the buffer.
+ ///
+ UINT8 **SupportedOptions;
+} EFI_MTFTP6_MODE_DATA;
+
+///
+/// EFI_MTFTP_OVERRIDE_DATA
+///
+typedef struct {
+ ///
+ /// IP address of the MTFTPv6 server. If set to all zero, the value that
+ /// was set by the EFI_MTFTP6_PROTOCOL.Configure() function will be used.
+ ///
+ EFI_IPv6_ADDRESS ServerIp;
+ ///
+ /// MTFTPv6 server port number. If set to zero, it will use the value
+ /// that was set by the EFI_MTFTP6_PROTOCOL.Configure() function.
+ ///
+ UINT16 ServerPort;
+ ///
+ /// Number of times to transmit MTFTPv6 request packets and wait
+ /// for a response. If set to zero, the value that was set by
+ /// theEFI_MTFTP6_PROTOCOL.Configure() function will be used.
+ ///
+ UINT16 TryCount;
+ ///
+ /// Number of seconds to wait for a response after sending the
+ /// MTFTPv6 request packet. If set to zero, the value that was set by
+ /// the EFI_MTFTP6_PROTOCOL.Configure() function will be used.
+ ///
+ UINT16 TimeoutValue;
+} EFI_MTFTP6_OVERRIDE_DATA;
+
+///
+/// EFI_MTFTP6_OPTION
+///
+typedef struct {
+ UINT8 *OptionStr; ///< Pointer to the null-terminated ASCII MTFTPv6 option string.
+ UINT8 *ValueStr; ///< Pointer to the null-terminated ASCII MTFTPv6 value string.
+} EFI_MTFTP6_OPTION;
+
+/**
+ EFI_MTFTP6_TIMEOUT_CALLBACK is a callback function that the caller provides to capture the
+ timeout event in the EFI_MTFTP6_PROTOCOL.ReadFile(), EFI_MTFTP6_PROTOCOL.WriteFile() or
+ EFI_MTFTP6_PROTOCOL.ReadDirectory() functions.
+
+ Whenever a timeout occurs, the EFI MTFTPv6 Protocol driver will call the EFI_MTFTP6_TIMEOUT_CALLBACK
+ function to notify the caller of the timeout event. Any status code other than EFI_SUCCESS
+ that is returned from this function will abort the current download process.
+
+ @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
+ @param[in] Token The token that the caller provided in the EFI_MTFTP6_PROTOCOl.ReadFile(),
+ WriteFile() or ReadDirectory() function.
+ @param[in] PacketLen Indicates the length of the packet.
+ @param[in] Packet Pointer to an MTFTPv6 packet.
+
+ @retval EFI_SUCCESS Operation success.
+ @retval Others Aborts session.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_MTFTP6_CHECK_PACKET)(
+ IN EFI_MTFTP6_PROTOCOL *This,
+ IN EFI_MTFTP6_TOKEN *Token,
+ IN UINT16 PacketLen,
+ IN EFI_MTFTP6_PACKET *Packet
+ );
+
+/**
+ EFI_MTFTP6_TIMEOUT_CALLBACK is a callback function that the caller provides to capture the
+ timeout event in the EFI_MTFTP6_PROTOCOL.ReadFile(), EFI_MTFTP6_PROTOCOL.WriteFile() or
+ EFI_MTFTP6_PROTOCOL.ReadDirectory() functions.
+
+ Whenever a timeout occurs, the EFI MTFTPv6 Protocol driver will call the EFI_MTFTP6_TIMEOUT_CALLBACK
+ function to notify the caller of the timeout event. Any status code other than EFI_SUCCESS
+ that is returned from this function will abort the current download process.
+
+ @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
+ @param[in] Token The token that is provided in the EFI_MTFTP6_PROTOCOL.ReadFile() or
+ EFI_MTFTP6_PROTOCOL.WriteFile() or EFI_MTFTP6_PROTOCOL.ReadDirectory()
+ functions by the caller.
+
+ @retval EFI_SUCCESS Operation success.
+ @retval Others Aborts session.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_MTFTP6_TIMEOUT_CALLBACK)(
+ IN EFI_MTFTP6_PROTOCOL *This,
+ IN EFI_MTFTP6_TOKEN *Token
+ );
+
+/**
+ EFI_MTFTP6_PACKET_NEEDED is a callback function that the caller provides to feed data to the
+ EFI_MTFTP6_PROTOCOL.WriteFile() function.
+
+ EFI_MTFTP6_PACKET_NEEDED provides another mechanism for the caller to provide data to upload
+ other than a static buffer. The EFI MTFTP6 Protocol driver always calls EFI_MTFTP6_PACKET_NEEDED
+ to get packet data from the caller if no static buffer was given in the initial call to
+ EFI_MTFTP6_PROTOCOL.WriteFile() function. Setting *Length to zero signals the end of the session.
+ Returning a status code other than EFI_SUCCESS aborts the session.
+
+ @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
+ @param[in] Token The token provided in the EFI_MTFTP6_PROTOCOL.WriteFile() by the caller.
+ @param[in, out] Length Indicates the length of the raw data wanted on input, and the
+ length the data available on output.
+ @param[out] Buffer Pointer to the buffer where the data is stored.
+
+ @retval EFI_SUCCESS Operation success.
+ @retval Others Aborts session.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_MTFTP6_PACKET_NEEDED)(
+ IN EFI_MTFTP6_PROTOCOL *This,
+ IN EFI_MTFTP6_TOKEN *Token,
+ IN OUT UINT16 *Length,
+ OUT VOID **Buffer
+ );
+
+struct _EFI_MTFTP6_TOKEN {
+ ///
+ /// The status that is returned to the caller at the end of the operation
+ /// to indicate whether this operation completed successfully.
+ /// Defined Status values are listed below.
+ ///
+ EFI_STATUS Status;
+ ///
+ /// The event that will be signaled when the operation completes. If
+ /// set to NULL, the corresponding function will wait until the read or
+ /// write operation finishes. The type of Event must be EVT_NOTIFY_SIGNAL.
+ ///
+ EFI_EVENT Event;
+ ///
+ /// If not NULL, the data that will be used to override the existing
+ /// configure data.
+ ///
+ EFI_MTFTP6_OVERRIDE_DATA *OverrideData;
+ ///
+ /// Pointer to the null-terminated ASCII file name string.
+ ///
+ UINT8 *Filename;
+ ///
+ /// Pointer to the null-terminated ASCII mode string. If NULL, octet is used.
+ ///
+ UINT8 *ModeStr;
+ ///
+ /// Number of option/value string pairs.
+ ///
+ UINT32 OptionCount;
+ ///
+ /// Pointer to an array of option/value string pairs. Ignored if
+ /// OptionCount is zero. Both a remote server and this driver
+ /// implementation should support these options. If one or more
+ /// options are unrecognized by this implementation, it is sent to the
+ /// remote server without being changed.
+ ///
+ EFI_MTFTP6_OPTION *OptionList;
+ ///
+ /// On input, the size, in bytes, of Buffer. On output, the number
+ /// of bytes transferred.
+ ///
+ UINT64 BufferSize;
+ ///
+ /// Pointer to the data buffer. Data that is downloaded from the
+ /// MTFTPv6 server is stored here. Data that is uploaded to the
+ /// MTFTPv6 server is read from here. Ignored if BufferSize is zero.
+ ///
+ VOID *Buffer;
+ ///
+ /// Pointer to the context that will be used by CheckPacket,
+ /// TimeoutCallback and PacketNeeded.
+ ///
+ VOID *Context;
+ ///
+ /// Pointer to the callback function to check the contents of the
+ /// received packet.
+ ///
+ EFI_MTFTP6_CHECK_PACKET CheckPacket;
+ ///
+ /// Pointer to the function to be called when a timeout occurs.
+ ///
+ EFI_MTFTP6_TIMEOUT_CALLBACK TimeoutCallback;
+ ///
+ /// Pointer to the function to provide the needed packet contents.
+ /// Only used in WriteFile() operation.
+ ///
+ EFI_MTFTP6_PACKET_NEEDED PacketNeeded;
+};
+
+/**
+ Read the current operational settings.
+
+ The GetModeData() function reads the current operational settings of this EFI MTFTPv6
+ Protocol driver instance.
+
+ @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
+ @param[out] ModeData The buffer in which the EFI MTFTPv6 Protocol driver mode
+ data is returned.
+
+ @retval EFI_SUCCESS The configuration data was successfully returned.
+ @retval EFI_OUT_OF_RESOURCES The required mode data could not be allocated.
+ @retval EFI_INVALID_PARAMETER This is NULL or ModeData is NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_MTFTP6_GET_MODE_DATA)(
+ IN EFI_MTFTP6_PROTOCOL *This,
+ OUT EFI_MTFTP6_MODE_DATA *ModeData
+ );
+
+/**
+ Initializes, changes, or resets the default operational setting for this EFI MTFTPv6
+ Protocol driver instance.
+
+ The Configure() function is used to set and change the configuration data for this EFI
+ MTFTPv6 Protocol driver instance. The configuration data can be reset to startup defaults by calling
+ Configure() with MtftpConfigData set to NULL. Whenever the instance is reset, any
+ pending operation is aborted. By changing the EFI MTFTPv6 Protocol driver instance configuration
+ data, the client can connect to different MTFTPv6 servers. The configuration parameters in
+ MtftpConfigData are used as the default parameters in later MTFTPv6 operations and can be
+ overridden in later operations.
+
+ @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
+ @param[in] MtftpConfigData Pointer to the configuration data structure.
+
+ @retval EFI_SUCCESS The EFI MTFTPv6 Protocol instance was configured successfully.
+ @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE:
+ - This is NULL.
+ - MtftpConfigData.StationIp is neither zero nor one
+ of the configured IP addresses in the underlying IPv6 driver.
+ - MtftpCofigData.ServerIp is not a valid IPv6 unicast address.
+ @retval EFI_ACCESS_DENIED - The configuration could not be changed at this time because there
+ is some MTFTP background operation in progress.
+ - MtftpCofigData.LocalPort is already in use.
+ @retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
+ address for this instance, but no source address was available for use.
+ @retval EFI_OUT_OF_RESOURCES The EFI MTFTPv6 Protocol driver instance data could not be
+ allocated.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI
+ MTFTPv6 Protocol driver instance is not configured.
+
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_MTFTP6_CONFIGURE)(
+ IN EFI_MTFTP6_PROTOCOL *This,
+ IN EFI_MTFTP6_CONFIG_DATA *MtftpConfigData OPTIONAL
+ );
+
+/**
+ Get information about a file from an MTFTPv6 server.
+
+ The GetInfo() function assembles an MTFTPv6 request packet with options, sends it to the
+ MTFTPv6 server, and may return an MTFTPv6 OACK, MTFTPv6 ERROR, or ICMP ERROR packet.
+ Retries occur only if no response packets are received from the MTFTPv6 server before the
+ timeout expires.
+
+ @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
+ @param[in] OverrideData Data that is used to override the existing parameters. If NULL, the
+ default parameters that were set in the EFI_MTFTP6_PROTOCOL.Configure()
+ function are used.
+ @param[in] Filename Pointer to null-terminated ASCII file name string.
+ @param[in] ModeStr Pointer to null-terminated ASCII mode string. If NULL, octet will be used
+ @param[in] OptionCount Number of option/value string pairs in OptionList.
+ @param[in] OptionList Pointer to array of option/value string pairs. Ignored if
+ OptionCount is zero.
+ @param[out] PacketLength The number of bytes in the returned packet.
+ @param[out] Packet The pointer to the received packet. This buffer must be freed by
+ the caller.
+
+ @retval EFI_SUCCESS An MTFTPv6 OACK packet was received and is in the Packet.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ - This is NULL.
+ - Filename is NULL
+ - OptionCount is not zero and OptionList is NULL.
+ - One or more options in OptionList have wrong format.
+ - PacketLength is NULL.
+ - OverrideData.ServerIp is not valid unicast IPv6 addresses.
+ @retval EFI_UNSUPPORTED One or more options in the OptionList are unsupported by
+ this implementation.
+ @retval EFI_NOT_STARTED The EFI MTFTPv6 Protocol driver has not been started.
+ @retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
+ address for this instance, but no source address was available for use.
+ @retval EFI_ACCESS_DENIED The previous operation has not completed yet.
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+ @retval EFI_TFTP_ERROR An MTFTPv6 ERROR packet was received and is in the Packet.
+ @retval EFI_NETWORK_UNREACHABLE An ICMP network unreachable error packet was received and the Packet is set to NULL.
+ @retval EFI_HOST_UNREACHABLE An ICMP host unreachable error packet was received and the Packet is set to NULL.
+ @retval EFI_PROTOCOL_UNREACHABLE An ICMP protocol unreachable error packet was received and the Packet is set to NULL.
+ @retval EFI_PORT_UNREACHABLE An ICMP port unreachable error packet was received and the Packet is set to NULL.
+ @retval EFI_ICMP_ERROR Some other ICMP ERROR packet was received and the Packet is set to NULL.
+ @retval EFI_PROTOCOL_ERROR An unexpected MTFTPv6 packet was received and is in the Packet.
+ @retval EFI_TIMEOUT No responses were received from the MTFTPv6 server.
+ @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
+ @retval EFI_NO_MEDIA There was a media error.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_MTFTP6_GET_INFO)(
+ IN EFI_MTFTP6_PROTOCOL *This,
+ IN EFI_MTFTP6_OVERRIDE_DATA *OverrideData OPTIONAL,
+ IN UINT8 *Filename,
+ IN UINT8 *ModeStr OPTIONAL,
+ IN UINT8 OptionCount,
+ IN EFI_MTFTP6_OPTION *OptionList OPTIONAL,
+ OUT UINT32 *PacketLength,
+ OUT EFI_MTFTP6_PACKET **Packet OPTIONAL
+ );
+
+/**
+ Parse the options in an MTFTPv6 OACK packet.
+
+ The ParseOptions() function parses the option fields in an MTFTPv6 OACK packet and
+ returns the number of options that were found and optionally a list of pointers to
+ the options in the packet.
+ If one or more of the option fields are not valid, then EFI_PROTOCOL_ERROR is returned
+ and *OptionCount and *OptionList stop at the last valid option.
+
+ @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
+ @param[in] PacketLen Length of the OACK packet to be parsed.
+ @param[in] Packet Pointer to the OACK packet to be parsed.
+ @param[out] OptionCount Pointer to the number of options in the following OptionList.
+ @param[out] OptionList Pointer to EFI_MTFTP6_OPTION storage. Each pointer in the
+ OptionList points to the corresponding MTFTP option buffer
+ in the Packet. Call the EFI Boot Service FreePool() to
+ release the OptionList if the options in this OptionList
+ are not needed any more.
+
+ @retval EFI_SUCCESS The OACK packet was valid and the OptionCount and
+ OptionList parameters have been updated.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ - PacketLen is 0.
+ - Packet is NULL or Packet is not a valid MTFTPv6 packet.
+ - OptionCount is NULL.
+ @retval EFI_NOT_FOUND No options were found in the OACK packet.
+ @retval EFI_OUT_OF_RESOURCES Storage for the OptionList array can not be allocated.
+ @retval EFI_PROTOCOL_ERROR One or more of the option fields is invalid.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_MTFTP6_PARSE_OPTIONS)(
+ IN EFI_MTFTP6_PROTOCOL *This,
+ IN UINT32 PacketLen,
+ IN EFI_MTFTP6_PACKET *Packet,
+ OUT UINT32 *OptionCount,
+ OUT EFI_MTFTP6_OPTION **OptionList OPTIONAL
+ );
+
+/**
+ Download a file from an MTFTPv6 server.
+
+ The ReadFile() function is used to initialize and start an MTFTPv6 download process and
+ optionally wait for completion. When the download operation completes, whether successfully or
+ not, the Token.Status field is updated by the EFI MTFTPv6 Protocol driver and then
+ Token.Event is signaled if it is not NULL.
+
+ Data can be downloaded from the MTFTPv6 server into either of the following locations:
+ - A fixed buffer that is pointed to by Token.Buffer
+ - A download service function that is pointed to by Token.CheckPacket
+
+ If both Token.Buffer and Token.CheckPacket are used, then Token.CheckPacket
+ will be called first. If the call is successful, the packet will be stored in Token.Buffer.
+
+ @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
+ @param[in] Token Pointer to the token structure to provide the parameters that are
+ used in this operation.
+
+ @retval EFI_SUCCESS The data file has been transferred successfully.
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+ @retval EFI_BUFFER_TOO_SMALL BufferSize is not zero but not large enough to hold the
+ downloaded data in downloading process.
+ @retval EFI_ABORTED Current operation is aborted by user.
+ @retval EFI_NETWORK_UNREACHABLE An ICMP network unreachable error packet was received.
+ @retval EFI_HOST_UNREACHABLE An ICMP host unreachable error packet was received.
+ @retval EFI_PROTOCOL_UNREACHABLE An ICMP protocol unreachable error packet was received.
+ @retval EFI_PORT_UNREACHABLE An ICMP port unreachable error packet was received.
+ @retval EFI_ICMP_ERROR An ICMP ERROR packet was received.
+ @retval EFI_TIMEOUT No responses were received from the MTFTPv6 server.
+ @retval EFI_TFTP_ERROR An MTFTPv6 ERROR packet was received.
+ @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
+ @retval EFI_NO_MEDIA There was a media error.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_MTFTP6_READ_FILE)(
+ IN EFI_MTFTP6_PROTOCOL *This,
+ IN EFI_MTFTP6_TOKEN *Token
+ );
+
+/**
+ Send a file to an MTFTPv6 server. May be unsupported in some implementations.
+
+ The WriteFile() function is used to initialize an uploading operation with the given option list
+ and optionally wait for completion. If one or more of the options is not supported by the server, the
+ unsupported options are ignored and a standard TFTP process starts instead. When the upload
+ process completes, whether successfully or not, Token.Event is signaled, and the EFI MTFTPv6
+ Protocol driver updates Token.Status.
+
+ The caller can supply the data to be uploaded in the following two modes:
+ - Through the user-provided buffer
+ - Through a callback function
+
+ With the user-provided buffer, the Token.BufferSize field indicates the length of the buffer,
+ and the driver will upload the data in the buffer. With an EFI_MTFTP6_PACKET_NEEDED
+ callback function, the driver will call this callback function to get more data from the user to upload.
+ See the definition of EFI_MTFTP6_PACKET_NEEDED for more information. These two modes
+ cannot be used at the same time. The callback function will be ignored if the user provides the
+ buffer.
+
+ @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
+ @param[in] Token Pointer to the token structure to provide the parameters that are
+ used in this operation.
+
+ @retval EFI_SUCCESS The upload session has started.
+ @retval EFI_UNSUPPORTED The operation is not supported by this implementation.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ - This is NULL.
+ - Token is NULL.
+ - Token.Filename is NULL.
+ - Token.OptionCount is not zero and Token.OptionList is NULL.
+ - One or more options in Token.OptionList have wrong format.
+ - Token.Buffer and Token.PacketNeeded are both NULL.
+ - Token.OverrideData.ServerIp is not valid unicast IPv6 addresses.
+ @retval EFI_UNSUPPORTED One or more options in the Token.OptionList are not
+ supported by this implementation.
+ @retval EFI_NOT_STARTED The EFI MTFTPv6 Protocol driver has not been started.
+ @retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
+ address for this instance, but no source address was available for use.
+ @retval EFI_ALREADY_STARTED This Token is already being used in another MTFTPv6 session.
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+ @retval EFI_ACCESS_DENIED The previous operation has not completed yet.
+ @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_MTFTP6_WRITE_FILE)(
+ IN EFI_MTFTP6_PROTOCOL *This,
+ IN EFI_MTFTP6_TOKEN *Token
+ );
+
+/**
+ Download a data file directory from an MTFTPv6 server. May be unsupported in some implementations.
+
+ The ReadDirectory() function is used to return a list of files on the MTFTPv6 server that are
+ logically (or operationally) related to Token.Filename. The directory request packet that is sent
+ to the server is built with the option list that was provided by caller, if present.
+
+ The file information that the server returns is put into either of the following locations:
+ - A fixed buffer that is pointed to by Token.Buffer
+ - A download service function that is pointed to by Token.CheckPacket
+
+ If both Token.Buffer and Token.CheckPacket are used, then Token.CheckPacket
+ will be called first. If the call is successful, the packet will be stored in Token.Buffer.
+
+ The returned directory listing in the Token.Buffer or EFI_MTFTP6_PACKET consists of a list
+ of two or three variable-length ASCII strings, each terminated by a null character, for each file in the
+ directory. If the multicast option is involved, the first field of each directory entry is the static
+ multicast IP address and UDP port number that is associated with the file name. The format of the
+ field is ip:ip:ip:ip:port. If the multicast option is not involved, this field and its terminating
+ null character are not present.
+
+ The next field of each directory entry is the file name and the last field is the file information string.
+ The information string contains the file size and the create/modify timestamp. The format of the
+ information string is filesize yyyy-mm-dd hh:mm:ss:ffff. The timestamp is
+ Coordinated Universal Time (UTC; also known as Greenwich Mean Time [GMT]).
+
+ @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
+ @param[in] Token Pointer to the token structure to provide the parameters that are
+ used in this operation.
+
+ @retval EFI_SUCCESS The MTFTPv6 related file "directory" has been downloaded.
+ @retval EFI_UNSUPPORTED The EFI MTFTPv6 Protocol driver does not support this function.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ - This is NULL.
+ - Token is NULL.
+ - Token.Filename is NULL.
+ - Token.OptionCount is not zero and Token.OptionList is NULL.
+ - One or more options in Token.OptionList have wrong format.
+ - Token.Buffer and Token.CheckPacket are both NULL.
+ - Token.OverrideData.ServerIp is not valid unicast IPv6 addresses.
+ @retval EFI_UNSUPPORTED One or more options in the Token.OptionList are not
+ supported by this implementation.
+ @retval EFI_NOT_STARTED The EFI MTFTPv6 Protocol driver has not been started.
+ @retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
+ address for this instance, but no source address was available for use.
+ @retval EFI_ALREADY_STARTED This Token is already being used in another MTFTPv6 session.
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+ @retval EFI_ACCESS_DENIED The previous operation has not completed yet.
+ @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_MTFTP6_READ_DIRECTORY)(
+ IN EFI_MTFTP6_PROTOCOL *This,
+ IN EFI_MTFTP6_TOKEN *Token
+ );
+
+/**
+ Polls for incoming data packets and processes outgoing data packets.
+
+ The Poll() function can be used by network drivers and applications to increase the rate that data
+ packets are moved between the communications device and the transmit and receive queues.
+ In some systems, the periodic timer event in the managed network driver may not poll the
+ underlying communications device fast enough to transmit and/or receive all data packets without
+ missing incoming packets or dropping outgoing packets. Drivers and applications that are
+ experiencing packet loss should try calling the Poll() function more often.
+
+ @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Incoming or outgoing data was processed.
+ @retval EFI_NOT_STARTED This EFI MTFTPv6 Protocol instance has not been started.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue.
+ Consider increasing the polling rate.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_MTFTP6_POLL)(
+ IN EFI_MTFTP6_PROTOCOL *This
+ );
+
+///
+/// The EFI_MTFTP6_PROTOCOL is designed to be used by UEFI drivers and applications to transmit
+/// and receive data files. The EFI MTFTPv6 Protocol driver uses the underlying EFI UDPv6 Protocol
+/// driver and EFI IPv6 Protocol driver.
+///
+struct _EFI_MTFTP6_PROTOCOL {
+ EFI_MTFTP6_GET_MODE_DATA GetModeData;
+ EFI_MTFTP6_CONFIGURE Configure;
+ EFI_MTFTP6_GET_INFO GetInfo;
+ EFI_MTFTP6_PARSE_OPTIONS ParseOptions;
+ EFI_MTFTP6_READ_FILE ReadFile;
+ EFI_MTFTP6_WRITE_FILE WriteFile;
+ EFI_MTFTP6_READ_DIRECTORY ReadDirectory;
+ EFI_MTFTP6_POLL Poll;
+};
+
+extern EFI_GUID gEfiMtftp6ServiceBindingProtocolGuid;
+extern EFI_GUID gEfiMtftp6ProtocolGuid;
+
+#endif
diff --git a/src/include/ipxe/efi/Protocol/ShimLock.h b/src/include/ipxe/efi/Protocol/ShimLock.h
new file mode 100644
index 00000000..b3136517
--- /dev/null
+++ b/src/include/ipxe/efi/Protocol/ShimLock.h
@@ -0,0 +1,31 @@
+#ifndef _IPXE_EFI_SHIM_LOCK_PROTOCOL_H
+#define _IPXE_EFI_SHIM_LOCK_PROTOCOL_H
+
+/** @file
+ *
+ * EFI "shim lock" protocol
+ *
+ */
+
+FILE_LICENCE ( BSD3 );
+
+#define EFI_SHIM_LOCK_PROTOCOL_GUID \
+ { 0x605dab50, 0xe046, 0x4300, \
+ { 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } }
+
+#define SHIMAPI __asmcall
+
+typedef
+EFI_STATUS SHIMAPI
+(*EFI_SHIM_LOCK_VERIFY) (
+ IN VOID *buffer,
+ IN UINT32 size
+ );
+
+typedef struct _EFI_SHIM_LOCK_PROTOCOL {
+ EFI_SHIM_LOCK_VERIFY Verify;
+ VOID *Reserved1;
+ VOID *Reserved2;
+} EFI_SHIM_LOCK_PROTOCOL;
+
+#endif /*_IPXE_EFI_SHIM_LOCK_PROTOCOL_H */
diff --git a/src/include/ipxe/efi/Protocol/Tcp6.h b/src/include/ipxe/efi/Protocol/Tcp6.h
new file mode 100644
index 00000000..eed2f7cc
--- /dev/null
+++ b/src/include/ipxe/efi/Protocol/Tcp6.h
@@ -0,0 +1,858 @@
+/** @file
+ EFI TCPv6(Transmission Control Protocol version 6) Protocol Definition
+ The EFI TCPv6 Service Binding Protocol is used to locate EFI TCPv6 Protocol drivers to create
+ and destroy child of the driver to communicate with other host using TCP protocol.
+ The EFI TCPv6 Protocol provides services to send and receive data stream.
+
+ Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Revision Reference:
+ This Protocol is introduced in UEFI Specification 2.2
+
+**/
+
+#ifndef __EFI_TCP6_PROTOCOL_H__
+#define __EFI_TCP6_PROTOCOL_H__
+
+FILE_LICENCE ( BSD2_PATENT );
+
+#include <ipxe/efi/Protocol/ManagedNetwork.h>
+#include <ipxe/efi/Protocol/Ip6.h>
+
+#define EFI_TCP6_SERVICE_BINDING_PROTOCOL_GUID \
+ { \
+ 0xec20eb79, 0x6c1a, 0x4664, {0x9a, 0x0d, 0xd2, 0xe4, 0xcc, 0x16, 0xd6, 0x64 } \
+ }
+
+#define EFI_TCP6_PROTOCOL_GUID \
+ { \
+ 0x46e44855, 0xbd60, 0x4ab7, {0xab, 0x0d, 0xa6, 0x79, 0xb9, 0x44, 0x7d, 0x77 } \
+ }
+
+typedef struct _EFI_TCP6_PROTOCOL EFI_TCP6_PROTOCOL;
+
+///
+/// EFI_TCP6_SERVICE_POINT is deprecated in the UEFI 2.4B and should not be used any more.
+/// The definition in here is only present to provide backwards compatability.
+///
+typedef struct {
+ ///
+ /// The EFI TCPv6 Protocol instance handle that is using this
+ /// address/port pair.
+ ///
+ EFI_HANDLE InstanceHandle;
+ ///
+ /// The local IPv6 address to which this TCP instance is bound. Set
+ /// to 0::/128, if this TCP instance is configured to listen on all
+ /// available source addresses.
+ ///
+ EFI_IPv6_ADDRESS LocalAddress;
+ ///
+ /// The local port number in host byte order.
+ ///
+ UINT16 LocalPort;
+ ///
+ /// The remote IPv6 address. It may be 0::/128 if this TCP instance is
+ /// not connected to any remote host.
+ ///
+ EFI_IPv6_ADDRESS RemoteAddress;
+ ///
+ /// The remote port number in host byte order. It may be zero if this
+ /// TCP instance is not connected to any remote host.
+ ///
+ UINT16 RemotePort;
+} EFI_TCP6_SERVICE_POINT;
+
+///
+/// EFI_TCP6_VARIABLE_DATA is deprecated in the UEFI 2.4B and should not be used any more.
+/// The definition in here is only present to provide backwards compatability.
+///
+typedef struct {
+ EFI_HANDLE DriverHandle; ///< The handle of the driver that creates this entry.
+ UINT32 ServiceCount; ///< The number of address/port pairs following this data structure.
+ EFI_TCP6_SERVICE_POINT Services[1]; ///< List of address/port pairs that are currently in use.
+} EFI_TCP6_VARIABLE_DATA;
+
+///
+/// EFI_TCP6_ACCESS_POINT
+///
+typedef struct {
+ ///
+ /// The local IP address assigned to this TCP instance. The EFI
+ /// TCPv6 driver will only deliver incoming packets whose
+ /// destination addresses exactly match the IP address. Set to zero to
+ /// let the underlying IPv6 driver choose a source address. If not zero
+ /// it must be one of the configured IP addresses in the underlying
+ /// IPv6 driver.
+ ///
+ EFI_IPv6_ADDRESS StationAddress;
+ ///
+ /// The local port number to which this EFI TCPv6 Protocol instance
+ /// is bound. If the instance doesn't care the local port number, set
+ /// StationPort to zero to use an ephemeral port.
+ ///
+ UINT16 StationPort;
+ ///
+ /// The remote IP address to which this EFI TCPv6 Protocol instance
+ /// is connected. If ActiveFlag is FALSE (i.e. a passive TCPv6
+ /// instance), the instance only accepts connections from the
+ /// RemoteAddress. If ActiveFlag is TRUE the instance will
+ /// connect to the RemoteAddress, i.e., outgoing segments will be
+ /// sent to this address and only segments from this address will be
+ /// delivered to the application. When ActiveFlag is FALSE, it
+ /// can be set to zero and means that incoming connection requests
+ /// from any address will be accepted.
+ ///
+ EFI_IPv6_ADDRESS RemoteAddress;
+ ///
+ /// The remote port to which this EFI TCPv6 Protocol instance
+ /// connects or from which connection request will be accepted by
+ /// this EFI TCPv6 Protocol instance. If ActiveFlag is FALSE it
+ /// can be zero and means that incoming connection request from
+ /// any port will be accepted. Its value can not be zero when
+ /// ActiveFlag is TRUE.
+ ///
+ UINT16 RemotePort;
+ ///
+ /// Set it to TRUE to initiate an active open. Set it to FALSE to
+ /// initiate a passive open to act as a server.
+ ///
+ BOOLEAN ActiveFlag;
+} EFI_TCP6_ACCESS_POINT;
+
+///
+/// EFI_TCP6_OPTION
+///
+typedef struct {
+ ///
+ /// The size of the TCP receive buffer.
+ ///
+ UINT32 ReceiveBufferSize;
+ ///
+ /// The size of the TCP send buffer.
+ ///
+ UINT32 SendBufferSize;
+ ///
+ /// The length of incoming connect request queue for a passive
+ /// instance. When set to zero, the value is implementation specific.
+ ///
+ UINT32 MaxSynBackLog;
+ ///
+ /// The maximum seconds a TCP instance will wait for before a TCP
+ /// connection established. When set to zero, the value is
+ /// implementation specific.
+ ///
+ UINT32 ConnectionTimeout;
+ ///
+ /// The number of times TCP will attempt to retransmit a packet on
+ /// an established connection. When set to zero, the value is
+ /// implementation specific.
+ ///
+ UINT32 DataRetries;
+ ///
+ /// How many seconds to wait in the FIN_WAIT_2 states for a final
+ /// FIN flag before the TCP instance is closed. This timeout is in
+ /// effective only if the application has called Close() to
+ /// disconnect the connection completely. It is also called
+ /// FIN_WAIT_2 timer in other implementations. When set to zero,
+ /// it should be disabled because the FIN_WAIT_2 timer itself is
+ /// against the standard. The default value is 60.
+ ///
+ UINT32 FinTimeout;
+ ///
+ /// How many seconds to wait in TIME_WAIT state before the TCP
+ /// instance is closed. The timer is disabled completely to provide a
+ /// method to close the TCP connection quickly if it is set to zero. It
+ /// is against the related RFC documents.
+ ///
+ UINT32 TimeWaitTimeout;
+ ///
+ /// The maximum number of TCP keep-alive probes to send before
+ /// giving up and resetting the connection if no response from the
+ /// other end. Set to zero to disable keep-alive probe.
+ ///
+ UINT32 KeepAliveProbes;
+ ///
+ /// The number of seconds a connection needs to be idle before TCP
+ /// sends out periodical keep-alive probes. When set to zero, the
+ /// value is implementation specific. It should be ignored if keep-
+ /// alive probe is disabled.
+ ///
+ UINT32 KeepAliveTime;
+ ///
+ /// The number of seconds between TCP keep-alive probes after the
+ /// periodical keep-alive probe if no response. When set to zero, the
+ /// value is implementation specific. It should be ignored if keep-
+ /// alive probe is disabled.
+ ///
+ UINT32 KeepAliveInterval;
+ ///
+ /// Set it to TRUE to enable the Nagle algorithm as defined in
+ /// RFC896. Set it to FALSE to disable it.
+ ///
+ BOOLEAN EnableNagle;
+ ///
+ /// Set it to TRUE to enable TCP timestamps option as defined in
+ /// RFC1323. Set to FALSE to disable it.
+ ///
+ BOOLEAN EnableTimeStamp;
+ ///
+ /// Set it to TRUE to enable TCP window scale option as defined in
+ /// RFC1323. Set it to FALSE to disable it.
+ ///
+ BOOLEAN EnableWindowScaling;
+ ///
+ /// Set it to TRUE to enable selective acknowledge mechanism
+ /// described in RFC 2018. Set it to FALSE to disable it.
+ /// Implementation that supports SACK can optionally support
+ /// DSAK as defined in RFC 2883.
+ ///
+ BOOLEAN EnableSelectiveAck;
+ ///
+ /// Set it to TRUE to enable path MTU discovery as defined in
+ /// RFC 1191. Set to FALSE to disable it.
+ ///
+ BOOLEAN EnablePathMtuDiscovery;
+} EFI_TCP6_OPTION;
+
+///
+/// EFI_TCP6_CONFIG_DATA
+///
+typedef struct {
+ ///
+ /// TrafficClass field in transmitted IPv6 packets.
+ ///
+ UINT8 TrafficClass;
+ ///
+ /// HopLimit field in transmitted IPv6 packets.
+ ///
+ UINT8 HopLimit;
+ ///
+ /// Used to specify TCP communication end settings for a TCP instance.
+ ///
+ EFI_TCP6_ACCESS_POINT AccessPoint;
+ ///
+ /// Used to configure the advance TCP option for a connection. If set
+ /// to NULL, implementation specific options for TCP connection will be used.
+ ///
+ EFI_TCP6_OPTION *ControlOption;
+} EFI_TCP6_CONFIG_DATA;
+
+///
+/// EFI_TCP6_CONNECTION_STATE
+///
+typedef enum {
+ Tcp6StateClosed = 0,
+ Tcp6StateListen = 1,
+ Tcp6StateSynSent = 2,
+ Tcp6StateSynReceived = 3,
+ Tcp6StateEstablished = 4,
+ Tcp6StateFinWait1 = 5,
+ Tcp6StateFinWait2 = 6,
+ Tcp6StateClosing = 7,
+ Tcp6StateTimeWait = 8,
+ Tcp6StateCloseWait = 9,
+ Tcp6StateLastAck = 10
+} EFI_TCP6_CONNECTION_STATE;
+
+///
+/// EFI_TCP6_COMPLETION_TOKEN
+/// is used as a common header for various asynchronous tokens.
+///
+typedef struct {
+ ///
+ /// The Event to signal after request is finished and Status field is
+ /// updated by the EFI TCPv6 Protocol driver.
+ ///
+ EFI_EVENT Event;
+ ///
+ /// The result of the completed operation.
+ ///
+ EFI_STATUS Status;
+} EFI_TCP6_COMPLETION_TOKEN;
+
+///
+/// EFI_TCP6_CONNECTION_TOKEN
+/// will be set if the active open succeeds or an unexpected
+/// error happens.
+///
+typedef struct {
+ ///
+ /// The Status in the CompletionToken will be set to one of
+ /// the following values if the active open succeeds or an unexpected
+ /// error happens:
+ /// EFI_SUCCESS: The active open succeeds and the instance's
+ /// state is Tcp6StateEstablished.
+ /// EFI_CONNECTION_RESET: The connect fails because the connection is reset
+ /// either by instance itself or the communication peer.
+ /// EFI_CONNECTION_REFUSED: The receiving or transmission operation fails because this
+ /// connection is refused.
+ /// EFI_ABORTED: The active open is aborted.
+ /// EFI_TIMEOUT: The connection establishment timer expires and
+ /// no more specific information is available.
+ /// EFI_NETWORK_UNREACHABLE: The active open fails because
+ /// an ICMP network unreachable error is received.
+ /// EFI_HOST_UNREACHABLE: The active open fails because an
+ /// ICMP host unreachable error is received.
+ /// EFI_PROTOCOL_UNREACHABLE: The active open fails
+ /// because an ICMP protocol unreachable error is received.
+ /// EFI_PORT_UNREACHABLE: The connection establishment
+ /// timer times out and an ICMP port unreachable error is received.
+ /// EFI_ICMP_ERROR: The connection establishment timer times
+ /// out and some other ICMP error is received.
+ /// EFI_DEVICE_ERROR: An unexpected system or network error occurred.
+ /// EFI_SECURITY_VIOLATION: The active open was failed because of IPSec policy check.
+ /// EFI_NO_MEDIA: There was a media error.
+ ///
+ EFI_TCP6_COMPLETION_TOKEN CompletionToken;
+} EFI_TCP6_CONNECTION_TOKEN;
+
+///
+/// EFI_TCP6_LISTEN_TOKEN
+/// returns when list operation finishes.
+///
+typedef struct {
+ ///
+ /// The Status in CompletionToken will be set to the
+ /// following value if accept finishes:
+ /// EFI_SUCCESS: A remote peer has successfully established a
+ /// connection to this instance. A new TCP instance has also been
+ /// created for the connection.
+ /// EFI_CONNECTION_RESET: The accept fails because the connection is reset either
+ /// by instance itself or communication peer.
+ /// EFI_ABORTED: The accept request has been aborted.
+ /// EFI_SECURITY_VIOLATION: The accept operation was failed because of IPSec policy check.
+ ///
+ EFI_TCP6_COMPLETION_TOKEN CompletionToken;
+ EFI_HANDLE NewChildHandle;
+} EFI_TCP6_LISTEN_TOKEN;
+
+///
+/// EFI_TCP6_FRAGMENT_DATA
+/// allows multiple receive or transmit buffers to be specified. The
+/// purpose of this structure is to provide scattered read and write.
+///
+typedef struct {
+ UINT32 FragmentLength; ///< Length of data buffer in the fragment.
+ VOID *FragmentBuffer; ///< Pointer to the data buffer in the fragment.
+} EFI_TCP6_FRAGMENT_DATA;
+
+///
+/// EFI_TCP6_RECEIVE_DATA
+/// When TCPv6 driver wants to deliver received data to the application,
+/// it will pick up the first queued receiving token, update its
+/// Token->Packet.RxData then signal the Token->CompletionToken.Event.
+///
+typedef struct {
+ ///
+ /// Whether the data is urgent. When this flag is set, the instance is in
+ /// urgent mode.
+ ///
+ BOOLEAN UrgentFlag;
+ ///
+ /// When calling Receive() function, it is the byte counts of all
+ /// Fragmentbuffer in FragmentTable allocated by user.
+ /// When the token is signaled by TCPv6 driver it is the length of
+ /// received data in the fragments.
+ ///
+ UINT32 DataLength;
+ ///
+ /// Number of fragments.
+ ///
+ UINT32 FragmentCount;
+ ///
+ /// An array of fragment descriptors.
+ ///
+ EFI_TCP6_FRAGMENT_DATA FragmentTable[1];
+} EFI_TCP6_RECEIVE_DATA;
+
+///
+/// EFI_TCP6_TRANSMIT_DATA
+/// The EFI TCPv6 Protocol user must fill this data structure before sending a packet.
+/// The packet may contain multiple buffers in non-continuous memory locations.
+///
+typedef struct {
+ ///
+ /// Push If TRUE, data must be transmitted promptly, and the PUSH bit in
+ /// the last TCP segment created will be set. If FALSE, data
+ /// transmission may be delayed to combine with data from
+ /// subsequent Transmit()s for efficiency.
+ ///
+ BOOLEAN Push;
+ ///
+ /// The data in the fragment table are urgent and urgent point is in
+ /// effect if TRUE. Otherwise those data are NOT considered urgent.
+ ///
+ BOOLEAN Urgent;
+ ///
+ /// Length of the data in the fragments.
+ ///
+ UINT32 DataLength;
+ ///
+ /// Number of fragments.
+ ///
+ UINT32 FragmentCount;
+ ///
+ /// An array of fragment descriptors.
+ ///
+ EFI_TCP6_FRAGMENT_DATA FragmentTable[1];
+} EFI_TCP6_TRANSMIT_DATA;
+
+///
+/// EFI_TCP6_IO_TOKEN
+/// returns When transmission finishes or meets any unexpected error.
+///
+typedef struct {
+ ///
+ /// When transmission finishes or meets any unexpected error it will
+ /// be set to one of the following values:
+ /// EFI_SUCCESS: The receiving or transmission operation
+ /// completes successfully.
+ /// EFI_CONNECTION_FIN: The receiving operation fails because the communication peer
+ /// has closed the connection and there is no more data in the
+ /// receive buffer of the instance.
+ /// EFI_CONNECTION_RESET: The receiving or transmission operation fails
+ /// because this connection is reset either by instance
+ /// itself or the communication peer.
+ /// EFI_ABORTED: The receiving or transmission is aborted.
+ /// EFI_TIMEOUT: The transmission timer expires and no more
+ /// specific information is available.
+ /// EFI_NETWORK_UNREACHABLE: The transmission fails
+ /// because an ICMP network unreachable error is received.
+ /// EFI_HOST_UNREACHABLE: The transmission fails because an
+ /// ICMP host unreachable error is received.
+ /// EFI_PROTOCOL_UNREACHABLE: The transmission fails
+ /// because an ICMP protocol unreachable error is received.
+ /// EFI_PORT_UNREACHABLE: The transmission fails and an
+ /// ICMP port unreachable error is received.
+ /// EFI_ICMP_ERROR: The transmission fails and some other
+ /// ICMP error is received.
+ /// EFI_DEVICE_ERROR: An unexpected system or network error occurs.
+ /// EFI_SECURITY_VIOLATION: The receiving or transmission
+ /// operation was failed because of IPSec policy check
+ /// EFI_NO_MEDIA: There was a media error.
+ ///
+ EFI_TCP6_COMPLETION_TOKEN CompletionToken;
+ union {
+ ///
+ /// When this token is used for receiving, RxData is a pointer to
+ /// EFI_TCP6_RECEIVE_DATA.
+ ///
+ EFI_TCP6_RECEIVE_DATA *RxData;
+ ///
+ /// When this token is used for transmitting, TxData is a pointer to
+ /// EFI_TCP6_TRANSMIT_DATA.
+ ///
+ EFI_TCP6_TRANSMIT_DATA *TxData;
+ } Packet;
+} EFI_TCP6_IO_TOKEN;
+
+///
+/// EFI_TCP6_CLOSE_TOKEN
+/// returns when close operation finishes.
+///
+typedef struct {
+ ///
+ /// When close finishes or meets any unexpected error it will be set
+ /// to one of the following values:
+ /// EFI_SUCCESS: The close operation completes successfully.
+ /// EFI_ABORTED: User called configure with NULL without close stopping.
+ /// EFI_SECURITY_VIOLATION: The close operation was failed because of IPSec policy check.
+ ///
+ EFI_TCP6_COMPLETION_TOKEN CompletionToken;
+ ///
+ /// Abort the TCP connection on close instead of the standard TCP
+ /// close process when it is set to TRUE. This option can be used to
+ /// satisfy a fast disconnect.
+ ///
+ BOOLEAN AbortOnClose;
+} EFI_TCP6_CLOSE_TOKEN;
+
+/**
+ Get the current operational status.
+
+ The GetModeData() function copies the current operational settings of this EFI TCPv6
+ Protocol instance into user-supplied buffers. This function can also be used to retrieve
+ the operational setting of underlying drivers such as IPv6, MNP, or SNP.
+
+ @param[in] This Pointer to the EFI_TCP6_PROTOCOL instance.
+ @param[out] Tcp6State The buffer in which the current TCP state is returned.
+ @param[out] Tcp6ConfigData The buffer in which the current TCP configuration is returned.
+ @param[out] Ip6ModeData The buffer in which the current IPv6 configuration data used by
+ the TCP instance is returned.
+ @param[out] MnpConfigData The buffer in which the current MNP configuration data used
+ indirectly by the TCP instance is returned.
+ @param[out] SnpModeData The buffer in which the current SNP mode data used indirectly by
+ the TCP instance is returned.
+
+ @retval EFI_SUCCESS The mode data was read.
+ @retval EFI_NOT_STARTED No configuration data is available because this instance hasn't
+ been started.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TCP6_GET_MODE_DATA)(
+ IN EFI_TCP6_PROTOCOL *This,
+ OUT EFI_TCP6_CONNECTION_STATE *Tcp6State OPTIONAL,
+ OUT EFI_TCP6_CONFIG_DATA *Tcp6ConfigData OPTIONAL,
+ OUT EFI_IP6_MODE_DATA *Ip6ModeData OPTIONAL,
+ OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL,
+ OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL
+ );
+
+/**
+ Initialize or brutally reset the operational parameters for this EFI TCPv6 instance.
+
+ The Configure() function does the following:
+ - Initialize this TCP instance, i.e., initialize the communication end settings and
+ specify active open or passive open for an instance.
+ - Reset this TCP instance brutally, i.e., cancel all pending asynchronous tokens, flush
+ transmission and receiving buffer directly without informing the communication peer.
+
+ No other TCPv6 Protocol operation except Poll() can be executed by this instance until
+ it is configured properly. For an active TCP instance, after a proper configuration it
+ may call Connect() to initiates the three-way handshake. For a passive TCP instance,
+ its state will transit to Tcp6StateListen after configuration, and Accept() may be
+ called to listen the incoming TCP connection requests. If Tcp6ConfigData is set to NULL,
+ the instance is reset. Resetting process will be done brutally, the state machine will
+ be set to Tcp6StateClosed directly, the receive queue and transmit queue will be flushed,
+ and no traffic is allowed through this instance.
+
+ @param[in] This Pointer to the EFI_TCP6_PROTOCOL instance.
+ @param[in] Tcp6ConfigData Pointer to the configure data to configure the instance.
+ If Tcp6ConfigData is set to NULL, the instance is reset.
+
+ @retval EFI_SUCCESS The operational settings are set, changed, or reset
+ successfully.
+ @retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
+ address for this instance, but no source address was available for
+ use.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions are TRUE:
+ - This is NULL.
+ - Tcp6ConfigData->AccessPoint.StationAddress is neither zero nor
+ one of the configured IP addresses in the underlying IPv6 driver.
+ - Tcp6ConfigData->AccessPoint.RemoteAddress isn't a valid unicast
+ IPv6 address.
+ - Tcp6ConfigData->AccessPoint.RemoteAddress is zero or
+ Tcp6ConfigData->AccessPoint.RemotePort is zero when
+ Tcp6ConfigData->AccessPoint.ActiveFlag is TRUE.
+ - A same access point has been configured in other TCP
+ instance properly.
+ @retval EFI_ACCESS_DENIED Configuring TCP instance when it is configured without
+ calling Configure() with NULL to reset it.
+ @retval EFI_UNSUPPORTED One or more of the control options are not supported in
+ the implementation.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources when
+ executing Configure().
+ @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TCP6_CONFIGURE)(
+ IN EFI_TCP6_PROTOCOL *This,
+ IN EFI_TCP6_CONFIG_DATA *Tcp6ConfigData OPTIONAL
+ );
+
+/**
+ Initiate a nonblocking TCP connection request for an active TCP instance.
+
+ The Connect() function will initiate an active open to the remote peer configured
+ in current TCP instance if it is configured active. If the connection succeeds or
+ fails due to any error, the ConnectionToken->CompletionToken.Event will be signaled
+ and ConnectionToken->CompletionToken.Status will be updated accordingly. This
+ function can only be called for the TCP instance in Tcp6StateClosed state. The
+ instance will transfer into Tcp6StateSynSent if the function returns EFI_SUCCESS.
+ If TCP three-way handshake succeeds, its state will become Tcp6StateEstablished,
+ otherwise, the state will return to Tcp6StateClosed.
+
+ @param[in] This Pointer to the EFI_TCP6_PROTOCOL instance.
+ @param[in] ConnectionToken Pointer to the connection token to return when the TCP three
+ way handshake finishes.
+
+ @retval EFI_SUCCESS The connection request is successfully initiated and the state of
+ this TCP instance has been changed to Tcp6StateSynSent.
+ @retval EFI_NOT_STARTED This EFI TCPv6 Protocol instance has not been configured.
+ @retval EFI_ACCESS_DENIED One or more of the following conditions are TRUE:
+ - This instance is not configured as an active one.
+ - This instance is not in Tcp6StateClosed state.
+ @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
+ - This is NULL.
+ - ConnectionToken is NULL.
+ - ConnectionToken->CompletionToken.Event is NULL.
+ @retval EFI_OUT_OF_RESOURCES The driver can't allocate enough resource to initiate the active open.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TCP6_CONNECT)(
+ IN EFI_TCP6_PROTOCOL *This,
+ IN EFI_TCP6_CONNECTION_TOKEN *ConnectionToken
+ );
+
+/**
+ Listen on the passive instance to accept an incoming connection request. This is a
+ nonblocking operation.
+
+ The Accept() function initiates an asynchronous accept request to wait for an incoming
+ connection on the passive TCP instance. If a remote peer successfully establishes a
+ connection with this instance, a new TCP instance will be created and its handle will
+ be returned in ListenToken->NewChildHandle. The newly created instance is configured
+ by inheriting the passive instance's configuration and is ready for use upon return.
+ The new instance is in the Tcp6StateEstablished state.
+
+ The ListenToken->CompletionToken.Event will be signaled when a new connection is
+ accepted, user aborts the listen or connection is reset.
+
+ This function only can be called when current TCP instance is in Tcp6StateListen state.
+
+ @param[in] This Pointer to the EFI_TCP6_PROTOCOL instance.
+ @param[in] ListenToken Pointer to the listen token to return when operation finishes.
+
+
+ @retval EFI_SUCCESS The listen token has been queued successfully.
+ @retval EFI_NOT_STARTED This EFI TCPv6 Protocol instance has not been configured.
+ @retval EFI_ACCESS_DENIED One or more of the following are TRUE:
+ - This instance is not a passive instance.
+ - This instance is not in Tcp6StateListen state.
+ - The same listen token has already existed in the listen
+ token queue of this TCP instance.
+ @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
+ - This is NULL.
+ - ListenToken is NULL.
+ - ListentToken->CompletionToken.Event is NULL.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate enough resource to finish the operation.
+ @retval EFI_DEVICE_ERROR Any unexpected and not belonged to above category error.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TCP6_ACCEPT)(
+ IN EFI_TCP6_PROTOCOL *This,
+ IN EFI_TCP6_LISTEN_TOKEN *ListenToken
+ );
+
+/**
+ Queues outgoing data into the transmit queue.
+
+ The Transmit() function queues a sending request to this TCP instance along with the
+ user data. The status of the token is updated and the event in the token will be
+ signaled once the data is sent out or some error occurs.
+
+ @param[in] This Pointer to the EFI_TCP6_PROTOCOL instance.
+ @param[in] Token Pointer to the completion token to queue to the transmit queue.
+
+ @retval EFI_SUCCESS The data has been queued for transmission.
+ @retval EFI_NOT_STARTED This EFI TCPv6 Protocol instance has not been configured.
+ @retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a
+ source address for this instance, but no source address was
+ available for use.
+ @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
+ - This is NULL.
+ - Token is NULL.
+ - Token->CompletionToken.Event is NULL.
+ - Token->Packet.TxData is NULL.
+ - Token->Packet.FragmentCount is zero.
+ - Token->Packet.DataLength is not equal to the sum of fragment lengths.
+ @retval EFI_ACCESS_DENIED One or more of the following conditions are TRUE:
+ - A transmit completion token with the same Token->
+ CompletionToken.Event was already in the
+ transmission queue.
+ - The current instance is in Tcp6StateClosed state.
+ - The current instance is a passive one and it is in
+ Tcp6StateListen state.
+ - User has called Close() to disconnect this connection.
+ @retval EFI_NOT_READY The completion token could not be queued because the
+ transmit queue is full.
+ @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data because of resource
+ shortage.
+ @retval EFI_NETWORK_UNREACHABLE There is no route to the destination network or address.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TCP6_TRANSMIT)(
+ IN EFI_TCP6_PROTOCOL *This,
+ IN EFI_TCP6_IO_TOKEN *Token
+ );
+
+/**
+ Places an asynchronous receive request into the receiving queue.
+
+ The Receive() function places a completion token into the receive packet queue. This
+ function is always asynchronous. The caller must allocate the Token->CompletionToken.Event
+ and the FragmentBuffer used to receive data. The caller also must fill the DataLength which
+ represents the whole length of all FragmentBuffer. When the receive operation completes, the
+ EFI TCPv6 Protocol driver updates the Token->CompletionToken.Status and Token->Packet.RxData
+ fields and the Token->CompletionToken.Event is signaled. If got data the data and its length
+ will be copied into the FragmentTable, at the same time the full length of received data will
+ be recorded in the DataLength fields. Providing a proper notification function and context
+ for the event will enable the user to receive the notification and receiving status. That
+ notification function is guaranteed to not be re-entered.
+
+ @param[in] This Pointer to the EFI_TCP6_PROTOCOL instance.
+ @param[in] Token Pointer to a token that is associated with the receive data
+ descriptor.
+
+ @retval EFI_SUCCESS The receive completion token was cached.
+ @retval EFI_NOT_STARTED This EFI TCPv6 Protocol instance has not been configured.
+ @retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
+ address for this instance, but no source address was available for use.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ - This is NULL.
+ - Token is NULL.
+ - Token->CompletionToken.Event is NULL.
+ - Token->Packet.RxData is NULL.
+ - Token->Packet.RxData->DataLength is 0.
+ - The Token->Packet.RxData->DataLength is not the
+ sum of all FragmentBuffer length in FragmentTable.
+ @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued due to a lack of
+ system resources (usually memory).
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ The EFI TCPv6 Protocol instance has been reset to startup defaults.
+ @retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE:
+ - A receive completion token with the same Token->CompletionToken.Event
+ was already in the receive queue.
+ - The current instance is in Tcp6StateClosed state.
+ - The current instance is a passive one and it is in
+ Tcp6StateListen state.
+ - User has called Close() to disconnect this connection.
+ @retval EFI_CONNECTION_FIN The communication peer has closed the connection and there is no
+ any buffered data in the receive buffer of this instance
+ @retval EFI_NOT_READY The receive request could not be queued because the receive queue is full.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TCP6_RECEIVE)(
+ IN EFI_TCP6_PROTOCOL *This,
+ IN EFI_TCP6_IO_TOKEN *Token
+ );
+
+/**
+ Disconnecting a TCP connection gracefully or reset a TCP connection. This function is a
+ nonblocking operation.
+
+ Initiate an asynchronous close token to TCP driver. After Close() is called, any buffered
+ transmission data will be sent by TCP driver and the current instance will have a graceful close
+ working flow described as RFC 793 if AbortOnClose is set to FALSE, otherwise, a rest packet
+ will be sent by TCP driver to fast disconnect this connection. When the close operation completes
+ successfully the TCP instance is in Tcp6StateClosed state, all pending asynchronous
+ operations are signaled and any buffers used for TCP network traffic are flushed.
+
+ @param[in] This Pointer to the EFI_TCP6_PROTOCOL instance.
+ @param[in] CloseToken Pointer to the close token to return when operation finishes.
+
+ @retval EFI_SUCCESS The Close() is called successfully.
+ @retval EFI_NOT_STARTED This EFI TCPv6 Protocol instance has not been configured.
+ @retval EFI_ACCESS_DENIED One or more of the following are TRUE:
+ - CloseToken or CloseToken->CompletionToken.Event is already in use.
+ - Previous Close() call on this instance has not finished.
+ @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
+ - This is NULL.
+ - CloseToken is NULL.
+ - CloseToken->CompletionToken.Event is NULL.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate enough resource to finish the operation.
+ @retval EFI_DEVICE_ERROR Any unexpected and not belonged to above category error.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TCP6_CLOSE)(
+ IN EFI_TCP6_PROTOCOL *This,
+ IN EFI_TCP6_CLOSE_TOKEN *CloseToken
+ );
+
+/**
+ Abort an asynchronous connection, listen, transmission or receive request.
+
+ The Cancel() function aborts a pending connection, listen, transmit or
+ receive request.
+
+ If Token is not NULL and the token is in the connection, listen, transmission
+ or receive queue when it is being cancelled, its Token->Status will be set
+ to EFI_ABORTED and then Token->Event will be signaled.
+
+ If the token is not in one of the queues, which usually means that the
+ asynchronous operation has completed, EFI_NOT_FOUND is returned.
+
+ If Token is NULL all asynchronous token issued by Connect(), Accept(),
+ Transmit() and Receive() will be aborted.
+
+ @param[in] This Pointer to the EFI_TCP6_PROTOCOL instance.
+ @param[in] Token Pointer to a token that has been issued by
+ EFI_TCP6_PROTOCOL.Connect(),
+ EFI_TCP6_PROTOCOL.Accept(),
+ EFI_TCP6_PROTOCOL.Transmit() or
+ EFI_TCP6_PROTOCOL.Receive(). If NULL, all pending
+ tokens issued by above four functions will be aborted. Type
+ EFI_TCP6_COMPLETION_TOKEN is defined in
+ EFI_TCP_PROTOCOL.Connect().
+
+ @retval EFI_SUCCESS The asynchronous I/O request is aborted and Token->Event
+ is signaled.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_NOT_STARTED This instance hasn't been configured.
+ @retval EFI_NOT_FOUND The asynchronous I/O request isn't found in the transmission or
+ receive queue. It has either completed or wasn't issued by
+ Transmit() and Receive().
+ @retval EFI_UNSUPPORTED The implementation does not support this function.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TCP6_CANCEL)(
+ IN EFI_TCP6_PROTOCOL *This,
+ IN EFI_TCP6_COMPLETION_TOKEN *Token OPTIONAL
+ );
+
+/**
+ Poll to receive incoming data and transmit outgoing segments.
+
+ The Poll() function increases the rate that data is moved between the network
+ and application and can be called when the TCP instance is created successfully.
+ Its use is optional.
+
+ @param[in] This Pointer to the EFI_TCP6_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Incoming or outgoing data was processed.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_NOT_READY No incoming or outgoing data is processed.
+ @retval EFI_TIMEOUT Data was dropped out of the transmission or receive queue.
+ Consider increasing the polling rate.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TCP6_POLL)(
+ IN EFI_TCP6_PROTOCOL *This
+ );
+
+///
+/// EFI_TCP6_PROTOCOL
+/// defines the EFI TCPv6 Protocol child to be used by any network drivers or
+/// applications to send or receive data stream. It can either listen on a
+/// specified port as a service or actively connect to remote peer as a client.
+/// Each instance has its own independent settings.
+///
+struct _EFI_TCP6_PROTOCOL {
+ EFI_TCP6_GET_MODE_DATA GetModeData;
+ EFI_TCP6_CONFIGURE Configure;
+ EFI_TCP6_CONNECT Connect;
+ EFI_TCP6_ACCEPT Accept;
+ EFI_TCP6_TRANSMIT Transmit;
+ EFI_TCP6_RECEIVE Receive;
+ EFI_TCP6_CLOSE Close;
+ EFI_TCP6_CANCEL Cancel;
+ EFI_TCP6_POLL Poll;
+};
+
+extern EFI_GUID gEfiTcp6ServiceBindingProtocolGuid;
+extern EFI_GUID gEfiTcp6ProtocolGuid;
+
+#endif
diff --git a/src/include/ipxe/efi/Protocol/Udp6.h b/src/include/ipxe/efi/Protocol/Udp6.h
new file mode 100644
index 00000000..5a62a3e0
--- /dev/null
+++ b/src/include/ipxe/efi/Protocol/Udp6.h
@@ -0,0 +1,576 @@
+/** @file
+ The EFI UDPv6 (User Datagram Protocol version 6) Protocol Definition, which is built upon
+ the EFI IPv6 Protocol and provides simple packet-oriented services to transmit and receive
+ UDP packets.
+
+ Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Revision Reference:
+ This Protocol is introduced in UEFI Specification 2.2
+
+**/
+
+#ifndef __EFI_UDP6_PROTOCOL_H__
+#define __EFI_UDP6_PROTOCOL_H__
+
+FILE_LICENCE ( BSD2_PATENT );
+
+#include <ipxe/efi/Protocol/Ip6.h>
+
+#define EFI_UDP6_SERVICE_BINDING_PROTOCOL_GUID \
+ { \
+ 0x66ed4721, 0x3c98, 0x4d3e, {0x81, 0xe3, 0xd0, 0x3d, 0xd3, 0x9a, 0x72, 0x54 } \
+ }
+
+#define EFI_UDP6_PROTOCOL_GUID \
+ { \
+ 0x4f948815, 0xb4b9, 0x43cb, {0x8a, 0x33, 0x90, 0xe0, 0x60, 0xb3, 0x49, 0x55 } \
+ }
+
+///
+/// EFI_UDP6_SERVICE_POINT is deprecated in the UEFI 2.4B and should not be used any more.
+/// The definition in here is only present to provide backwards compatability.
+///
+typedef struct {
+ ///
+ /// The EFI UDPv6 Protocol instance handle that is using this address/port pair.
+ ///
+ EFI_HANDLE InstanceHandle;
+ ///
+ /// The IPv6 address to which this instance of the EFI UDPv6 Protocol is bound.
+ /// Set to 0::/128, if this instance is used to listen all packets from any
+ /// source address.
+ ///
+ EFI_IPv6_ADDRESS LocalAddress;
+ ///
+ /// The port number in host byte order on which the service is listening.
+ ///
+ UINT16 LocalPort;
+ ///
+ /// The IPv6 address of the remote host. May be 0::/128 if it is not connected
+ /// to any remote host or connected with more than one remote host.
+ ///
+ EFI_IPv6_ADDRESS RemoteAddress;
+ ///
+ /// The port number in host byte order on which the remote host is
+ /// listening. Maybe zero if it is not connected to any remote host.
+ ///
+ UINT16 RemotePort;
+} EFI_UDP6_SERVICE_POINT;
+
+///
+/// EFI_UDP6_VARIABLE_DATA is deprecated in the UEFI 2.4B and should not be used any more.
+/// The definition in here is only present to provide backwards compatability.
+///
+typedef struct {
+ ///
+ /// The handle of the driver that creates this entry.
+ ///
+ EFI_HANDLE DriverHandle;
+ ///
+ /// The number of address/port pairs that follow this data structure.
+ ///
+ UINT32 ServiceCount;
+ ///
+ /// List of address/port pairs that are currently in use.
+ ///
+ EFI_UDP6_SERVICE_POINT Services[1];
+} EFI_UDP6_VARIABLE_DATA;
+
+typedef struct _EFI_UDP6_PROTOCOL EFI_UDP6_PROTOCOL;
+
+///
+/// EFI_UDP6_FRAGMENT_DATA allows multiple receive or transmit buffers to be specified.
+/// The purpose of this structure is to avoid copying the same packet multiple times.
+///
+typedef struct {
+ UINT32 FragmentLength; ///< Length of the fragment data buffer.
+ VOID *FragmentBuffer; ///< Pointer to the fragment data buffer.
+} EFI_UDP6_FRAGMENT_DATA;
+
+///
+/// The EFI_UDP6_SESSION_DATA is used to retrieve the settings when receiving packets or
+/// to override the existing settings (only DestinationAddress and DestinationPort can
+/// be overridden) of this EFI UDPv6 Protocol instance when sending packets.
+///
+typedef struct {
+ ///
+ /// Address from which this packet is sent. This field should not be used when
+ /// sending packets.
+ ///
+ EFI_IPv6_ADDRESS SourceAddress;
+ ///
+ /// Port from which this packet is sent. It is in host byte order. This field should
+ /// not be used when sending packets.
+ ///
+ UINT16 SourcePort;
+ ///
+ /// Address to which this packet is sent. When sending packet, it'll be ignored
+ /// if it is zero.
+ ///
+ EFI_IPv6_ADDRESS DestinationAddress;
+ ///
+ /// Port to which this packet is sent. When sending packet, it'll be
+ /// ignored if it is zero.
+ ///
+ UINT16 DestinationPort;
+} EFI_UDP6_SESSION_DATA;
+
+typedef struct {
+ ///
+ /// Set to TRUE to accept UDP packets that are sent to any address.
+ ///
+ BOOLEAN AcceptPromiscuous;
+ ///
+ /// Set to TRUE to accept UDP packets that are sent to any port.
+ ///
+ BOOLEAN AcceptAnyPort;
+ ///
+ /// Set to TRUE to allow this EFI UDPv6 Protocol child instance to open a port number
+ /// that is already being used by another EFI UDPv6 Protocol child instance.
+ ///
+ BOOLEAN AllowDuplicatePort;
+ ///
+ /// TrafficClass field in transmitted IPv6 packets.
+ ///
+ UINT8 TrafficClass;
+ ///
+ /// HopLimit field in transmitted IPv6 packets.
+ ///
+ UINT8 HopLimit;
+ ///
+ /// The receive timeout value (number of microseconds) to be associated with each
+ /// incoming packet. Zero means do not drop incoming packets.
+ ///
+ UINT32 ReceiveTimeout;
+ ///
+ /// The transmit timeout value (number of microseconds) to be associated with each
+ /// outgoing packet. Zero means do not drop outgoing packets.
+ ///
+ UINT32 TransmitTimeout;
+ ///
+ /// The station IP address that will be assigned to this EFI UDPv6 Protocol instance.
+ /// The EFI UDPv6 and EFI IPv6 Protocol drivers will only deliver incoming packets
+ /// whose destination matches this IP address exactly. Address 0::/128 is also accepted
+ /// as a special case. Under this situation, underlying IPv6 driver is responsible for
+ /// binding a source address to this EFI IPv6 protocol instance according to source
+ /// address selection algorithm. Only incoming packet from the selected source address
+ /// is delivered. This field can be set and changed only when the EFI IPv6 driver is
+ /// transitioning from the stopped to the started states. If no address is available
+ /// for selecting, the EFI IPv6 Protocol driver will use EFI_IP6_CONFIG_PROTOCOL to
+ /// retrieve the IPv6 address.
+ EFI_IPv6_ADDRESS StationAddress;
+ ///
+ /// The port number to which this EFI UDPv6 Protocol instance is bound. If a client
+ /// of the EFI UDPv6 Protocol does not care about the port number, set StationPort
+ /// to zero. The EFI UDPv6 Protocol driver will assign a random port number to transmitted
+ /// UDP packets. Ignored it if AcceptAnyPort is TRUE.
+ ///
+ UINT16 StationPort;
+ ///
+ /// The IP address of remote host to which this EFI UDPv6 Protocol instance is connecting.
+ /// If RemoteAddress is not 0::/128, this EFI UDPv6 Protocol instance will be connected to
+ /// RemoteAddress; i.e., outgoing packets of this EFI UDPv6 Protocol instance will be sent
+ /// to this address by default and only incoming packets from this address will be delivered
+ /// to client. Ignored for incoming filtering if AcceptPromiscuous is TRUE.
+ EFI_IPv6_ADDRESS RemoteAddress;
+ ///
+ /// The port number of the remote host to which this EFI UDPv6 Protocol instance is connecting.
+ /// If it is not zero, outgoing packets of this EFI UDPv6 Protocol instance will be sent to
+ /// this port number by default and only incoming packets from this port will be delivered
+ /// to client. Ignored if RemoteAddress is 0::/128 and ignored for incoming filtering if
+ /// AcceptPromiscuous is TRUE.
+ UINT16 RemotePort;
+} EFI_UDP6_CONFIG_DATA;
+
+///
+/// The EFI UDPv6 Protocol client must fill this data structure before sending a packet.
+/// The packet may contain multiple buffers that may be not in a continuous memory location.
+///
+typedef struct {
+ ///
+ /// If not NULL, the data that is used to override the transmitting settings.Only the two
+ /// filed UdpSessionData.DestinationAddress and UdpSessionData.DestionPort can be used as
+ /// the transmitting setting filed.
+ ///
+ EFI_UDP6_SESSION_DATA *UdpSessionData;
+ ///
+ /// Sum of the fragment data length. Must not exceed the maximum UDP packet size.
+ ///
+ UINT32 DataLength;
+ ///
+ /// Number of fragments.
+ ///
+ UINT32 FragmentCount;
+ ///
+ /// Array of fragment descriptors.
+ ///
+ EFI_UDP6_FRAGMENT_DATA FragmentTable[1];
+} EFI_UDP6_TRANSMIT_DATA;
+
+///
+/// EFI_UDP6_RECEIVE_DATA is filled by the EFI UDPv6 Protocol driver when this EFI UDPv6
+/// Protocol instance receives an incoming packet. If there is a waiting token for incoming
+/// packets, the CompletionToken.Packet.RxData field is updated to this incoming packet and
+/// the CompletionToken.Event is signaled. The EFI UDPv6 Protocol client must signal the
+/// RecycleSignal after processing the packet.
+/// FragmentTable could contain multiple buffers that are not in the continuous memory locations.
+/// The EFI UDPv6 Protocol client might need to combine two or more buffers in FragmentTable to
+/// form their own protocol header.
+///
+typedef struct {
+ ///
+ /// Time when the EFI UDPv6 Protocol accepted the packet.
+ ///
+ EFI_TIME TimeStamp;
+ ///
+ /// Indicates the event to signal when the received data has been processed.
+ ///
+ EFI_EVENT RecycleSignal;
+ ///
+ /// The UDP session data including SourceAddress, SourcePort, DestinationAddress,
+ /// and DestinationPort.
+ ///
+ EFI_UDP6_SESSION_DATA UdpSession;
+ ///
+ /// The sum of the fragment data length.
+ ///
+ UINT32 DataLength;
+ ///
+ /// Number of fragments. Maybe zero.
+ ///
+ UINT32 FragmentCount;
+ ///
+ /// Array of fragment descriptors. Maybe zero.
+ ///
+ EFI_UDP6_FRAGMENT_DATA FragmentTable[1];
+} EFI_UDP6_RECEIVE_DATA;
+
+///
+/// The EFI_UDP6_COMPLETION_TOKEN structures are used for both transmit and receive operations.
+/// When used for transmitting, the Event and TxData fields must be filled in by the EFI UDPv6
+/// Protocol client. After the transmit operation completes, the Status field is updated by the
+/// EFI UDPv6 Protocol and the Event is signaled.
+/// When used for receiving, only the Event field must be filled in by the EFI UDPv6 Protocol
+/// client. After a packet is received, RxData and Status are filled in by the EFI UDPv6 Protocol
+/// and the Event is signaled.
+///
+typedef struct {
+ ///
+ /// This Event will be signaled after the Status field is updated by the EFI UDPv6 Protocol
+ /// driver. The type of Event must be EVT_NOTIFY_SIGNAL.
+ ///
+ EFI_EVENT Event;
+ ///
+ /// Will be set to one of the following values:
+ /// - EFI_SUCCESS: The receive or transmit operation completed successfully.
+ /// - EFI_ABORTED: The receive or transmit was aborted.
+ /// - EFI_TIMEOUT: The transmit timeout expired.
+ /// - EFI_NETWORK_UNREACHABLE: The destination network is unreachable. RxData is set to
+ /// NULL in this situation.
+ /// - EFI_HOST_UNREACHABLE: The destination host is unreachable. RxData is set to NULL in
+ /// this situation.
+ /// - EFI_PROTOCOL_UNREACHABLE: The UDP protocol is unsupported in the remote system.
+ /// RxData is set to NULL in this situation.
+ /// - EFI_PORT_UNREACHABLE: No service is listening on the remote port. RxData is set to
+ /// NULL in this situation.
+ /// - EFI_ICMP_ERROR: Some other Internet Control Message Protocol (ICMP) error report was
+ /// received. For example, packets are being sent too fast for the destination to receive them
+ /// and the destination sent an ICMP source quench report. RxData is set to NULL in this situation.
+ /// - EFI_DEVICE_ERROR: An unexpected system or network error occurred.
+ /// - EFI_SECURITY_VIOLATION: The transmit or receive was failed because of IPsec policy check.
+ /// - EFI_NO_MEDIA: There was a media error.
+ ///
+ EFI_STATUS Status;
+ union {
+ ///
+ /// When this token is used for receiving, RxData is a pointer to EFI_UDP6_RECEIVE_DATA.
+ ///
+ EFI_UDP6_RECEIVE_DATA *RxData;
+ ///
+ /// When this token is used for transmitting, TxData is a pointer to EFI_UDP6_TRANSMIT_DATA.
+ ///
+ EFI_UDP6_TRANSMIT_DATA *TxData;
+ } Packet;
+} EFI_UDP6_COMPLETION_TOKEN;
+
+/**
+ Read the current operational settings.
+
+ The GetModeData() function copies the current operational settings of this EFI UDPv6 Protocol
+ instance into user-supplied buffers. This function is used optionally to retrieve the operational
+ mode data of underlying networks or drivers.
+
+ @param[in] This Pointer to the EFI_UDP6_PROTOCOL instance.
+ @param[out] Udp6ConfigData The buffer in which the current UDP configuration data is returned.
+ @param[out] Ip6ModeData The buffer in which the current EFI IPv6 Protocol mode data is returned.
+ @param[out] MnpConfigData The buffer in which the current managed network configuration data is
+ returned.
+ @param[out] SnpModeData The buffer in which the simple network mode data is returned.
+
+ @retval EFI_SUCCESS The mode data was read.
+ @retval EFI_NOT_STARTED When Udp6ConfigData is queried, no configuration data is available
+ because this instance has not been started.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_UDP6_GET_MODE_DATA)(
+ IN EFI_UDP6_PROTOCOL *This,
+ OUT EFI_UDP6_CONFIG_DATA *Udp6ConfigData OPTIONAL,
+ OUT EFI_IP6_MODE_DATA *Ip6ModeData OPTIONAL,
+ OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL,
+ OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL
+ );
+
+/**
+ Initializes, changes, or resets the operational parameters for this instance of the EFI UDPv6
+ Protocol.
+
+ The Configure() function is used to do the following:
+ - Initialize and start this instance of the EFI UDPv6 Protocol.
+ - Change the filtering rules and operational parameters.
+ - Reset this instance of the EFI UDPv6 Protocol.
+
+ Until these parameters are initialized, no network traffic can be sent or received by this instance.
+ This instance can be also reset by calling Configure() with UdpConfigData set to NULL.
+ Once reset, the receiving queue and transmitting queue are flushed and no traffic is allowed through
+ this instance.
+
+ With different parameters in UdpConfigData, Configure() can be used to bind this instance to specified
+ port.
+
+ @param[in] This Pointer to the EFI_UDP6_PROTOCOL instance.
+ @param[in] UdpConfigData Pointer to the buffer contained the configuration data.
+
+ @retval EFI_SUCCESS The configuration settings were set, changed, or reset successfully.
+ @retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
+ address for this instance, but no source address was available for use.
+ @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE:
+ - This is NULL.
+ - UdpConfigData.StationAddress neither zero nor one of the configured IP
+ addresses in the underlying IPv6 driver.
+ - UdpConfigData.RemoteAddress is not a valid unicast IPv6 address if it
+ is not zero.
+ @retval EFI_ALREADY_STARTED The EFI UDPv6 Protocol instance is already started/configured and must be
+ stopped/reset before it can be reconfigured. Only TrafficClass, HopLimit,
+ ReceiveTimeout, and TransmitTimeout can be reconfigured without stopping
+ the current instance of the EFI UDPv6 Protocol.
+ @retval EFI_ACCESS_DENIED UdpConfigData.AllowDuplicatePort is FALSE and UdpConfigData.StationPort
+ is already used by other instance.
+ @retval EFI_OUT_OF_RESOURCES The EFI UDPv6 Protocol driver cannot allocate memory for this EFI UDPv6
+ Protocol instance.
+ @retval EFI_DEVICE_ERROR An unexpected network or system error occurred and this instance was not
+ opened.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_UDP6_CONFIGURE)(
+ IN EFI_UDP6_PROTOCOL *This,
+ IN EFI_UDP6_CONFIG_DATA *UdpConfigData OPTIONAL
+ );
+
+/**
+ Joins and leaves multicast groups.
+
+ The Groups() function is used to join or leave one or more multicast group.
+ If the JoinFlag is FALSE and the MulticastAddress is NULL, then all currently joined groups are left.
+
+ @param[in] This Pointer to the EFI_UDP6_PROTOCOL instance.
+ @param[in] JoinFlag Set to TRUE to join a multicast group. Set to FALSE to leave one
+ or all multicast groups.
+ @param[in] MulticastAddress Pointer to multicast group address to join or leave.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_NOT_STARTED The EFI UDPv6 Protocol instance has not been started.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate resources to join the group.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ - This is NULL.
+ - JoinFlag is TRUE and MulticastAddress is NULL.
+ - JoinFlag is TRUE and *MulticastAddress is not a valid multicast address.
+ @retval EFI_ALREADY_STARTED The group address is already in the group table (when JoinFlag is TRUE).
+ @retval EFI_NOT_FOUND The group address is not in the group table (when JoinFlag is FALSE).
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_UDP6_GROUPS)(
+ IN EFI_UDP6_PROTOCOL *This,
+ IN BOOLEAN JoinFlag,
+ IN EFI_IPv6_ADDRESS *MulticastAddress OPTIONAL
+ );
+
+/**
+ Queues outgoing data packets into the transmit queue.
+
+ The Transmit() function places a sending request to this instance of the EFI UDPv6 Protocol,
+ alongside the transmit data that was filled by the user. Whenever the packet in the token is
+ sent out or some errors occur, the Token.Event will be signaled and Token.Status is updated.
+ Providing a proper notification function and context for the event will enable the user to
+ receive the notification and transmitting status.
+
+ @param[in] This Pointer to the EFI_UDP6_PROTOCOL instance.
+ @param[in] Token Pointer to the completion token that will be placed into the
+ transmit queue.
+
+ @retval EFI_SUCCESS The data has been queued for transmission.
+ @retval EFI_NOT_STARTED This EFI UDPv6 Protocol instance has not been started.
+ @retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
+ address for this instance, but no source address was available
+ for use.
+ @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
+ - This is NULL.
+ - Token is NULL.
+ - Token.Event is NULL.
+ - Token.Packet.TxData is NULL.
+ - Token.Packet.TxData.FragmentCount is zero.
+ - Token.Packet.TxData.DataLength is not equal to the sum of fragment
+ lengths.
+ - One or more of the Token.Packet.TxData.FragmentTable[].FragmentLength
+ fields is zero.
+ - One or more of the Token.Packet.TxData.FragmentTable[].FragmentBuffer
+ fields is NULL.
+ - Token.Packet.TxData.UdpSessionData.DestinationAddress is not zero
+ and is not valid unicast Ipv6 address if UdpSessionData is not NULL.
+ - Token.Packet.TxData.UdpSessionData is NULL and this instance's
+ UdpConfigData.RemoteAddress is unspecified.
+ - Token.Packet.TxData.UdpSessionData.DestinationAddress is non-zero
+ when DestinationAddress is configured as non-zero when doing Configure()
+ for this EFI Udp6 protocol instance.
+ - Token.Packet.TxData.UdpSesionData.DestinationAddress is zero when
+ DestinationAddress is unspecified when doing Configure() for this
+ EFI Udp6 protocol instance.
+ @retval EFI_ACCESS_DENIED The transmit completion token with the same Token.Event was already
+ in the transmit queue.
+ @retval EFI_NOT_READY The completion token could not be queued because the transmit queue
+ is full.
+ @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data.
+ @retval EFI_NOT_FOUND There is no route to the destination network or address.
+ @retval EFI_BAD_BUFFER_SIZE The data length is greater than the maximum UDP packet size.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_UDP6_TRANSMIT)(
+ IN EFI_UDP6_PROTOCOL *This,
+ IN EFI_UDP6_COMPLETION_TOKEN *Token
+ );
+
+/**
+ Places an asynchronous receive request into the receiving queue.
+
+ The Receive() function places a completion token into the receive packet queue. This function is
+ always asynchronous.
+ The caller must fill in the Token.Event field in the completion token, and this field cannot be
+ NULL. When the receive operation completes, the EFI UDPv6 Protocol driver updates the Token.Status
+ and Token.Packet.RxData fields and the Token.Event is signaled.
+ Providing a proper notification function and context for the event will enable the user to receive
+ the notification and receiving status. That notification function is guaranteed to not be re-entered.
+
+ @param[in] This Pointer to the EFI_UDP6_PROTOCOL instance.
+ @param[in] Token Pointer to a token that is associated with the receive data descriptor.
+
+ @retval EFI_SUCCESS The receive completion token was cached.
+ @retval EFI_NOT_STARTED This EFI UDPv6 Protocol instance has not been started.
+ @retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
+ address for this instance, but no source address was available
+ for use.
+ @retval EFI_INVALID_PARAMETER One or more of the following is TRUE:
+ - This is NULL.
+ - Token is NULL.
+ - Token.Event is NULL.
+ @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued due to a lack of system
+ resources (usually memory).
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI UDPv6 Protocol
+ instance has been reset to startup defaults.
+ @retval EFI_ACCESS_DENIED A receive completion token with the same Token.Event was already in
+ the receive queue.
+ @retval EFI_NOT_READY The receive request could not be queued because the receive queue is full.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_UDP6_RECEIVE)(
+ IN EFI_UDP6_PROTOCOL *This,
+ IN EFI_UDP6_COMPLETION_TOKEN *Token
+ );
+
+/**
+ Aborts an asynchronous transmit or receive request.
+
+ The Cancel() function is used to abort a pending transmit or receive request. If the token is in the
+ transmit or receive request queues, after calling this function, Token.Status will be set to
+ EFI_ABORTED and then Token.Event will be signaled. If the token is not in one of the queues,
+ which usually means that the asynchronous operation has completed, this function will not signal the
+ token and EFI_NOT_FOUND is returned.
+
+ @param[in] This Pointer to the EFI_UDP6_PROTOCOL instance.
+ @param[in] Token Pointer to a token that has been issued by EFI_UDP6_PROTOCOL.Transmit()
+ or EFI_UDP6_PROTOCOL.Receive().If NULL, all pending tokens are aborted.
+
+ @retval EFI_SUCCESS The asynchronous I/O request was aborted and Token.Event was signaled.
+ When Token is NULL, all pending requests are aborted and their events
+ are signaled.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_NOT_STARTED This instance has not been started.
+ @retval EFI_NOT_FOUND When Token is not NULL, the asynchronous I/O request was not found in
+ the transmit or receive queue. It has either completed or was not issued
+ by Transmit() and Receive().
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_UDP6_CANCEL)(
+ IN EFI_UDP6_PROTOCOL *This,
+ IN EFI_UDP6_COMPLETION_TOKEN *Token OPTIONAL
+ );
+
+/**
+ Polls for incoming data packets and processes outgoing data packets.
+
+ The Poll() function can be used by network drivers and applications to increase the rate that data
+ packets are moved between the communications device and the transmit and receive queues.
+ In some systems, the periodic timer event in the managed network driver may not poll the underlying
+ communications device fast enough to transmit and/or receive all data packets without missing incoming
+ packets or dropping outgoing packets. Drivers and applications that are experiencing packet loss should
+ try calling the Poll() function more often.
+
+ @param[in] This Pointer to the EFI_UDP6_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Incoming or outgoing data was processed.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue.
+ Consider increasing the polling rate.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_UDP6_POLL)(
+ IN EFI_UDP6_PROTOCOL *This
+ );
+
+///
+/// The EFI_UDP6_PROTOCOL defines an EFI UDPv6 Protocol session that can be used by any network drivers,
+/// applications, or daemons to transmit or receive UDP packets. This protocol instance can either be
+/// bound to a specified port as a service or connected to some remote peer as an active client.
+/// Each instance has its own settings, such as group table, that are independent from each other.
+///
+struct _EFI_UDP6_PROTOCOL {
+ EFI_UDP6_GET_MODE_DATA GetModeData;
+ EFI_UDP6_CONFIGURE Configure;
+ EFI_UDP6_GROUPS Groups;
+ EFI_UDP6_TRANSMIT Transmit;
+ EFI_UDP6_RECEIVE Receive;
+ EFI_UDP6_CANCEL Cancel;
+ EFI_UDP6_POLL Poll;
+};
+
+extern EFI_GUID gEfiUdp6ServiceBindingProtocolGuid;
+extern EFI_GUID gEfiUdp6ProtocolGuid;
+
+#endif
diff --git a/src/include/ipxe/efi/Uefi/UefiSpec.h b/src/include/ipxe/efi/Uefi/UefiSpec.h
index 3ef66daf..e5a32d88 100644
--- a/src/include/ipxe/efi/Uefi/UefiSpec.h
+++ b/src/include/ipxe/efi/Uefi/UefiSpec.h
@@ -467,8 +467,8 @@ EFI_STATUS
(EFIAPI *EFI_CREATE_EVENT)(
IN UINT32 Type,
IN EFI_TPL NotifyTpl,
- IN EFI_EVENT_NOTIFY NotifyFunction,
- IN VOID *NotifyContext,
+ IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL,
+ IN VOID *NotifyContext OPTIONAL,
OUT EFI_EVENT *Event
);
diff --git a/src/include/ipxe/efi/X64/ProcessorBind.h b/src/include/ipxe/efi/X64/ProcessorBind.h
index fa53404e..062a77ba 100644
--- a/src/include/ipxe/efi/X64/ProcessorBind.h
+++ b/src/include/ipxe/efi/X64/ProcessorBind.h
@@ -23,20 +23,6 @@ FILE_LICENCE ( BSD2_PATENT );
#pragma pack()
#endif
-#if defined (__GNUC__) && defined (__pic__) && !defined (USING_LTO) && !defined (__APPLE__)
-//
-// Mark all symbol declarations and references as hidden, meaning they will
-// not be subject to symbol preemption. This allows the compiler to refer to
-// symbols directly using relative references rather than via the GOT, which
-// contains absolute symbol addresses that are subject to runtime relocation.
-//
-// The LTO linker will not emit GOT based relocations when all symbol
-// references can be resolved locally, and so there is no need to set the
-// pragma in that case (and doing so will cause other issues).
-//
- #pragma GCC visibility push (hidden)
-#endif
-
#if defined (__INTEL_COMPILER)
//
// Disable ICC's remark #869: "Parameter" was never referenced warning.
@@ -105,18 +91,14 @@ FILE_LICENCE ( BSD2_PATENT );
#if defined (_MSC_VER) && _MSC_VER >= 1800
//
-// Disable these warnings for VS2013.
-//
-
-//
// This warning is for potentially uninitialized local variable, and it may cause false
-// positive issues in VS2013 and VS2015 build
+// positive issues in VS2015 build
//
#pragma warning ( disable : 4701 )
//
// This warning is for potentially uninitialized local pointer variable, and it may cause
-// false positive issues in VS2013 and VS2015 build
+// false positive issues in VS2015 build
//
#pragma warning ( disable : 4703 )
diff --git a/src/include/ipxe/efi/efi.h b/src/include/ipxe/efi/efi.h
index 1dd0d445..2137b824 100644
--- a/src/include/ipxe/efi/efi.h
+++ b/src/include/ipxe/efi/efi.h
@@ -43,10 +43,19 @@ FILE_LICENCE ( GPL2_OR_LATER );
* checking somewhat useless. Work around this bizarre sabotage
* attempt by redefining EFI_HANDLE as a pointer to an anonymous
* structure.
+ *
+ * EFI headers perform some ABI validation checks via _Static_assert()
+ * that may fail when EFI headers are included on a non-EFI platform.
+ * Temporarily disable static assertions to allow these headers to be
+ * included.
*/
#define EFI_HANDLE STUPID_EFI_HANDLE
+#ifndef PLATFORM_efi
+#define _Static_assert(expr, msg)
+#endif
#include <ipxe/efi/Uefi/UefiBaseType.h>
#undef EFI_HANDLE
+#undef _Static_assert
typedef struct {} *EFI_HANDLE;
/* Include the top-level EFI header files */
@@ -175,14 +184,26 @@ extern EFI_GUID efi_console_control_protocol_guid;
extern EFI_GUID efi_device_path_protocol_guid;
extern EFI_GUID efi_dhcp4_protocol_guid;
extern EFI_GUID efi_dhcp4_service_binding_protocol_guid;
+extern EFI_GUID efi_dhcp6_protocol_guid;
+extern EFI_GUID efi_dhcp6_service_binding_protocol_guid;
extern EFI_GUID efi_disk_io_protocol_guid;
+extern EFI_GUID efi_dns4_protocol_guid;
+extern EFI_GUID efi_dns4_service_binding_protocol_guid;
+extern EFI_GUID efi_dns6_protocol_guid;
+extern EFI_GUID efi_dns6_service_binding_protocol_guid;
extern EFI_GUID efi_driver_binding_protocol_guid;
extern EFI_GUID efi_graphics_output_protocol_guid;
extern EFI_GUID efi_hii_config_access_protocol_guid;
extern EFI_GUID efi_hii_font_protocol_guid;
+extern EFI_GUID efi_http_protocol_guid;
+extern EFI_GUID efi_http_service_binding_protocol_guid;
extern EFI_GUID efi_ip4_protocol_guid;
extern EFI_GUID efi_ip4_config_protocol_guid;
+extern EFI_GUID efi_ip4_config2_protocol_guid;
extern EFI_GUID efi_ip4_service_binding_protocol_guid;
+extern EFI_GUID efi_ip6_protocol_guid;
+extern EFI_GUID efi_ip6_config_protocol_guid;
+extern EFI_GUID efi_ip6_service_binding_protocol_guid;
extern EFI_GUID efi_load_file_protocol_guid;
extern EFI_GUID efi_load_file2_protocol_guid;
extern EFI_GUID efi_loaded_image_protocol_guid;
@@ -191,12 +212,15 @@ extern EFI_GUID efi_managed_network_protocol_guid;
extern EFI_GUID efi_managed_network_service_binding_protocol_guid;
extern EFI_GUID efi_mtftp4_protocol_guid;
extern EFI_GUID efi_mtftp4_service_binding_protocol_guid;
+extern EFI_GUID efi_mtftp6_protocol_guid;
+extern EFI_GUID efi_mtftp6_service_binding_protocol_guid;
extern EFI_GUID efi_nii_protocol_guid;
extern EFI_GUID efi_nii31_protocol_guid;
extern EFI_GUID efi_pci_io_protocol_guid;
extern EFI_GUID efi_pci_root_bridge_io_protocol_guid;
extern EFI_GUID efi_pxe_base_code_protocol_guid;
extern EFI_GUID efi_serial_io_protocol_guid;
+extern EFI_GUID efi_shim_lock_protocol_guid;
extern EFI_GUID efi_simple_file_system_protocol_guid;
extern EFI_GUID efi_simple_network_protocol_guid;
extern EFI_GUID efi_simple_pointer_protocol_guid;
@@ -206,9 +230,13 @@ extern EFI_GUID efi_simple_text_output_protocol_guid;
extern EFI_GUID efi_tcg_protocol_guid;
extern EFI_GUID efi_tcp4_protocol_guid;
extern EFI_GUID efi_tcp4_service_binding_protocol_guid;
+extern EFI_GUID efi_tcp6_protocol_guid;
+extern EFI_GUID efi_tcp6_service_binding_protocol_guid;
extern EFI_GUID efi_tree_protocol_guid;
extern EFI_GUID efi_udp4_protocol_guid;
extern EFI_GUID efi_udp4_service_binding_protocol_guid;
+extern EFI_GUID efi_udp6_protocol_guid;
+extern EFI_GUID efi_udp6_service_binding_protocol_guid;
extern EFI_GUID efi_uga_draw_protocol_guid;
extern EFI_GUID efi_unicode_collation_protocol_guid;
extern EFI_GUID efi_usb_hc_protocol_guid;
@@ -241,6 +269,7 @@ efi_handle_name ( EFI_HANDLE handle );
extern void dbg_efi_opener ( EFI_HANDLE handle, EFI_GUID *protocol,
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *opener );
extern void dbg_efi_openers ( EFI_HANDLE handle, EFI_GUID *protocol );
+extern void dbg_efi_protocol ( EFI_HANDLE handle, EFI_GUID *protocol );
extern void dbg_efi_protocols ( EFI_HANDLE handle );
#define DBG_EFI_OPENER_IF( level, handle, protocol, \
@@ -275,6 +304,12 @@ extern void dbg_efi_protocols ( EFI_HANDLE handle );
DBG_DC_IF ( level ); \
} while ( 0 )
+#define DBGC_EFI_PROTOCOL_IF( level, id, ... ) do { \
+ DBG_AC_IF ( level, id ); \
+ DBG_EFI_PROTOCOL_IF ( level, __VA_ARGS__ ); \
+ DBG_DC_IF ( level ); \
+ } while ( 0 )
+
#define DBGC_EFI_PROTOCOLS_IF( level, id, ... ) do { \
DBG_AC_IF ( level, id ); \
DBG_EFI_PROTOCOLS_IF ( level, __VA_ARGS__ ); \
@@ -285,6 +320,8 @@ extern void dbg_efi_protocols ( EFI_HANDLE handle );
DBGC_EFI_OPENER_IF ( LOG, ##__VA_ARGS__ )
#define DBGC_EFI_OPENERS( ... ) \
DBGC_EFI_OPENERS_IF ( LOG, ##__VA_ARGS__ )
+#define DBGC_EFI_PROTOCOL( ... ) \
+ DBGC_EFI_PROTOCOL_IF ( LOG, ##__VA_ARGS__ )
#define DBGC_EFI_PROTOCOLS( ... ) \
DBGC_EFI_PROTOCOLS_IF ( LOG, ##__VA_ARGS__ )
@@ -292,6 +329,8 @@ extern void dbg_efi_protocols ( EFI_HANDLE handle );
DBGC_EFI_OPENER_IF ( EXTRA, ##__VA_ARGS__ )
#define DBGC2_EFI_OPENERS( ... ) \
DBGC_EFI_OPENERS_IF ( EXTRA, ##__VA_ARGS__ )
+#define DBGC2_EFI_PROTOCOL( ... ) \
+ DBGC_EFI_PROTOCOL_IF ( EXTRA, ##__VA_ARGS__ )
#define DBGC2_EFI_PROTOCOLS( ... ) \
DBGC_EFI_PROTOCOLS_IF ( EXTRA, ##__VA_ARGS__ )
@@ -299,6 +338,8 @@ extern void dbg_efi_protocols ( EFI_HANDLE handle );
DBGC_EFI_OPENER_IF ( PROFILE, ##__VA_ARGS__ )
#define DBGCP_EFI_OPENERS( ... ) \
DBGC_EFI_OPENERS_IF ( PROFILE, ##__VA_ARGS__ )
+#define DBGCP_EFI_PROTOCOL( ... ) \
+ DBGC_EFI_PROTOCOL_IF ( PROFILE, ##__VA_ARGS__ )
#define DBGCP_EFI_PROTOCOLS( ... ) \
DBGC_EFI_PROTOCOLS_IF ( PROFILE, ##__VA_ARGS__ )
diff --git a/src/include/ipxe/efi/efi_image.h b/src/include/ipxe/efi/efi_image.h
new file mode 100644
index 00000000..0fc0402b
--- /dev/null
+++ b/src/include/ipxe/efi/efi_image.h
@@ -0,0 +1,27 @@
+#ifndef _IPXE_EFI_IMAGE_H
+#define _IPXE_EFI_IMAGE_H
+
+/** @file
+ *
+ * EFI images
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <ipxe/image.h>
+
+extern struct image_type efi_image_type[] __image_type ( PROBE_NORMAL );
+
+/**
+ * Check if EFI image can be loaded directly
+ *
+ * @v image EFI image
+ * @ret can_load EFI image can be loaded directly
+ */
+static inline int efi_can_load ( struct image *image ) {
+
+ return ( image->type == efi_image_type );
+}
+
+#endif /* _IPXE_EFI_IMAGE_H */
diff --git a/src/include/ipxe/efi/efi_shim.h b/src/include/ipxe/efi/efi_shim.h
new file mode 100644
index 00000000..21f24315
--- /dev/null
+++ b/src/include/ipxe/efi/efi_shim.h
@@ -0,0 +1,24 @@
+#ifndef _IPXE_EFI_SHIM_H
+#define _IPXE_EFI_SHIM_H
+
+/** @file
+ *
+ * UEFI shim special handling
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <ipxe/image.h>
+#include <ipxe/efi/efi.h>
+
+extern int efi_shim_require_loader;
+extern int efi_shim_allow_pxe;
+extern int efi_shim_allow_sbat;
+extern struct image_tag efi_shim __image_tag;
+
+extern int efi_shim_install ( struct image *shim, EFI_HANDLE handle,
+ wchar_t **cmdline );
+extern void efi_shim_uninstall ( void );
+
+#endif /* _IPXE_EFI_SHIM_H */
diff --git a/src/include/ipxe/efi/efi_strings.h b/src/include/ipxe/efi/efi_strings.h
index a8ace45e..a7adff82 100644
--- a/src/include/ipxe/efi/efi_strings.h
+++ b/src/include/ipxe/efi/efi_strings.h
@@ -19,6 +19,8 @@ extern int efi_vssnprintf ( wchar_t *wbuf, ssize_t swsize, const char *fmt,
va_list args );
extern int efi_ssnprintf ( wchar_t *wbuf, ssize_t swsize,
const char *fmt, ... );
+extern int efi_vasprintf ( wchar_t **strp, const char *fmt, va_list args );
+extern int efi_asprintf ( wchar_t **strp, const char *fmt, ... );
/**
* Write a formatted string to a wide-character buffer
diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h
index e6fd8524..320835a3 100644
--- a/src/include/ipxe/errfile.h
+++ b/src/include/ipxe/errfile.h
@@ -78,6 +78,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define ERRFILE_dma ( ERRFILE_CORE | 0x00260000 )
#define ERRFILE_cachedhcp ( ERRFILE_CORE | 0x00270000 )
#define ERRFILE_acpimac ( ERRFILE_CORE | 0x00280000 )
+#define ERRFILE_efi_strings ( ERRFILE_CORE | 0x00290000 )
#define ERRFILE_eisa ( ERRFILE_DRIVER | 0x00000000 )
#define ERRFILE_isa ( ERRFILE_DRIVER | 0x00010000 )
@@ -404,6 +405,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define ERRFILE_dhe ( ERRFILE_OTHER | 0x005a0000 )
#define ERRFILE_efi_cmdline ( ERRFILE_OTHER | 0x005b0000 )
#define ERRFILE_efi_rng ( ERRFILE_OTHER | 0x005c0000 )
+#define ERRFILE_efi_shim ( ERRFILE_OTHER | 0x005d0000 )
+#define ERRFILE_efi_settings ( ERRFILE_OTHER | 0x005e0000 )
/** @} */
diff --git a/src/include/ipxe/image.h b/src/include/ipxe/image.h
index 9e0c0f22..bfbf2368 100644
--- a/src/include/ipxe/image.h
+++ b/src/include/ipxe/image.h
@@ -61,16 +61,16 @@ struct image {
};
/** Image is registered */
-#define IMAGE_REGISTERED 0x00001
-
-/** Image is selected for execution */
-#define IMAGE_SELECTED 0x0002
+#define IMAGE_REGISTERED 0x0001
/** Image is trusted */
-#define IMAGE_TRUSTED 0x0004
+#define IMAGE_TRUSTED 0x0002
/** Image will be automatically unregistered after execution */
-#define IMAGE_AUTO_UNREGISTER 0x0008
+#define IMAGE_AUTO_UNREGISTER 0x0004
+
+/** Image will be hidden from enumeration */
+#define IMAGE_HIDDEN 0x0008
/** An executable image type */
struct image_type {
@@ -150,8 +150,23 @@ struct image_type {
/** An executable image type */
#define __image_type( probe_order ) __table_entry ( IMAGE_TYPES, probe_order )
+/** An image tag */
+struct image_tag {
+ /** Name */
+ const char *name;
+ /** Image (weak reference, nullified when image is freed) */
+ struct image *image;
+};
+
+/** Image tag table */
+#define IMAGE_TAGS __table ( struct image_tag, "image_tags" )
+
+/** An image tag */
+#define __image_tag __table_entry ( IMAGE_TAGS, 01 )
+
extern struct list_head images;
-extern struct image *current_image;
+extern struct image_tag current_image;
+extern struct image_tag selected_image;
/** Iterate over all registered images */
#define for_each_image( image ) \
@@ -162,15 +177,6 @@ extern struct image *current_image;
list_for_each_entry_safe ( (image), (tmp), &images, list )
/**
- * Test for existence of images
- *
- * @ret existence Some images exist
- */
-static inline int have_images ( void ) {
- return ( ! list_empty ( &images ) );
-}
-
-/**
* Retrieve first image
*
* @ret image Image, or NULL
@@ -187,11 +193,11 @@ extern int image_set_len ( struct image *image, size_t len );
extern int image_set_data ( struct image *image, userptr_t data, size_t len );
extern int register_image ( struct image *image );
extern void unregister_image ( struct image *image );
-struct image * find_image ( const char *name );
+extern struct image * find_image ( const char *name );
+extern struct image * find_image_tag ( struct image_tag *tag );
extern int image_exec ( struct image *image );
extern int image_replace ( struct image *replacement );
extern int image_select ( struct image *image );
-extern struct image * image_find_selected ( void );
extern int image_set_trust ( int require_trusted, int permanent );
extern struct image * image_memory ( const char *name, userptr_t data,
size_t len );
@@ -250,4 +256,28 @@ static inline void image_untrust ( struct image *image ) {
image->flags &= ~IMAGE_TRUSTED;
}
+/**
+ * Mark image as hidden
+ *
+ * @v image Image
+ */
+static inline void image_hide ( struct image *image ) {
+ image->flags |= IMAGE_HIDDEN;
+}
+
+/**
+ * Tag image
+ *
+ * @v image Image
+ * @v tag Image tag
+ * @ret prev Previous tagged image (if any)
+ */
+static inline struct image * image_tag ( struct image *image,
+ struct image_tag *tag ) {
+ struct image *prev = tag->image;
+
+ tag->image = image;
+ return prev;
+}
+
#endif /* _IPXE_IMAGE_H */
diff --git a/src/include/ipxe/interface.h b/src/include/ipxe/interface.h
index 19f58a4b..d2fa8190 100644
--- a/src/include/ipxe/interface.h
+++ b/src/include/ipxe/interface.h
@@ -133,17 +133,30 @@ struct interface {
struct interface *dest;
/** Reference counter
*
- * If this interface is not part of a reference-counted
- * object, this field may be NULL.
+ * If this interface is not part of a reference-counted object
+ * then this field is NULL.
*/
struct refcnt *refcnt;
- /** Interface descriptor */
- struct interface_descriptor *desc;
- /** Original interface descriptor
+ /** Interface descriptor
*
- * Used by intf_reinit().
+ * If this is a temporary outbound-only interface created by
+ * intf_temp_init() then this field is NULL.
*/
- struct interface_descriptor *original;
+ struct interface_descriptor *desc;
+ /** Original interface properties */
+ union {
+ /** Original interface descriptor
+ *
+ * Used by intf_reinit().
+ */
+ struct interface_descriptor *desc;
+ /** Original interface
+ *
+ * Used for temporary outbound-only interfaces created
+ * by intf_temp_init().
+ */
+ struct interface *intf;
+ } original;
};
extern void intf_plug ( struct interface *intf, struct interface *dest );
@@ -193,7 +206,7 @@ static inline void intf_init ( struct interface *intf,
intf->dest = &null_intf;
intf->refcnt = refcnt;
intf->desc = desc;
- intf->original = desc;
+ intf->original.desc = desc;
}
/**
@@ -201,14 +214,39 @@ static inline void intf_init ( struct interface *intf,
*
* @v descriptor Object interface descriptor
*/
-#define INTF_INIT( descriptor ) { \
- .dest = &null_intf, \
- .refcnt = NULL, \
- .desc = &(descriptor), \
- .original = &(descriptor), \
+#define INTF_INIT( descriptor ) { \
+ .dest = &null_intf, \
+ .refcnt = NULL, \
+ .desc = &(descriptor), \
+ .original = { \
+ .desc = &(descriptor), \
+ }, \
}
/**
+ * Initialise a temporary outbound-only object interface
+ *
+ * @v intf Temporary outbound-only object interface
+ * @v original Original object interface
+ */
+static inline void intf_temp_init ( struct interface *intf,
+ struct interface *original ) {
+ intf->dest = &null_intf;
+ intf->desc = NULL;
+ intf->original.intf = original;
+}
+
+/**
+ * Get original interface
+ *
+ * @v intf Object interface (possibly a temporary interface)
+ * @ret intf Original object interface
+ */
+static inline struct interface * intf_origin ( struct interface *intf ) {
+ return ( intf->desc ? intf : intf->original.intf );
+}
+
+/**
* Get object interface destination and operation method (without pass-through)
*
* @v intf Object interface
@@ -240,7 +278,7 @@ static inline void intf_init ( struct interface *intf,
*
* Use as the first argument to DBGC() or equivalent macro.
*/
-#define INTF_COL( intf ) intf_object ( intf )
+#define INTF_COL( intf ) intf_object ( intf_origin ( intf ) )
/** printf() format string for INTF_DBG() */
#define INTF_FMT "%p+%zx"
@@ -251,7 +289,9 @@ static inline void intf_init ( struct interface *intf,
* @v intf Object interface
* @ret args printf() argument list corresponding to INTF_FMT
*/
-#define INTF_DBG( intf ) intf_object ( intf ), (intf)->desc->offset
+#define INTF_DBG( intf ) \
+ intf_object ( intf_origin ( intf ) ), \
+ intf_origin ( intf )->desc->offset
/** printf() format string for INTF_INTF_DBG() */
#define INTF_INTF_FMT INTF_FMT "->" INTF_FMT
@@ -273,7 +313,7 @@ static inline void intf_init ( struct interface *intf,
static inline void intf_reinit ( struct interface *intf ) {
/* Restore original interface descriptor */
- intf->desc = intf->original;
+ intf->desc = intf->original.desc;
}
#endif /* _IPXE_INTERFACE_H */
diff --git a/src/include/ipxe/keymap.h b/src/include/ipxe/keymap.h
index 8bfbe07a..49a8915e 100644
--- a/src/include/ipxe/keymap.h
+++ b/src/include/ipxe/keymap.h
@@ -52,10 +52,10 @@ struct keymap {
#define KEYMAP_PSEUDO 0x80
/** Ctrl key flag */
-#define KEYMAP_CTRL 0x0100
+#define KEYMAP_CTRL 0x01000000
/** CapsLock key flag */
-#define KEYMAP_CAPSLOCK 0x0200
+#define KEYMAP_CAPSLOCK 0x02000000
/** Undo CapsLock key flag
*
@@ -64,13 +64,13 @@ struct keymap {
* in order to correctly handle keyboard mappings that swap alphabetic
* and non-alphabetic keys.
*/
-#define KEYMAP_CAPSLOCK_UNDO 0x0400
+#define KEYMAP_CAPSLOCK_UNDO 0x04000000
/** Undo and redo CapsLock key flags */
#define KEYMAP_CAPSLOCK_REDO ( KEYMAP_CAPSLOCK | KEYMAP_CAPSLOCK_UNDO )
/** AltGr key flag */
-#define KEYMAP_ALTGR 0x0800
+#define KEYMAP_ALTGR 0x08000000
extern unsigned int key_remap ( unsigned int character );
extern struct keymap * keymap_find ( const char *name );
diff --git a/src/include/ipxe/keys.h b/src/include/ipxe/keys.h
index d15267a1..49e65fa4 100644
--- a/src/include/ipxe/keys.h
+++ b/src/include/ipxe/keys.h
@@ -49,19 +49,58 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define ESC 0x1b
/*
- * Special keys outside the normal ASCII range
- *
+ * Special keys outside the normal Unicode range
*
* The names are chosen to match those used by curses. The values are
* chosen to facilitate easy conversion from a received ANSI escape
* sequence to a KEY_XXX constant.
+ *
+ * Note that the values are exposed to iPXE commands via parse_key()
+ * and therefore may not be changed without breaking existing scripts.
+ */
+
+/**
+ * Minimum value for special keypresses
+ *
+ * This value is chosen to lie above the maximum Unicode code point
+ * value 0x10ffff.
+ */
+#define KEY_MIN 0x110000
+
+/**
+ * Construct relative key value for special key
+ *
+ * @v key Key value
+ * @ret rkey Relative key value
*/
+#define KEY_REL( key ) ( (key) - KEY_MIN )
-#define KEY_ANSI( n, terminator ) ( 0x100 * ( (n) + 1 ) + (terminator) )
-#define KEY_ANSI_N( key ) ( ( (key) / 0x100 ) - 1 )
+/**
+ * Construct ANSI escape sequence key value
+ *
+ * @v n ANSI escape sequence numeric portion, or 0 for none
+ * @v terminator ANSI escape sequence terminating character
+ * @ret key Key value
+ */
+#define KEY_ANSI( n, terminator ) \
+ ( KEY_MIN + ( ( (n) + 1 ) << 8 ) + (terminator) )
+
+/**
+ * Extract ANSI escape sequence numeric portion
+ *
+ * @v key Key value (or relative key value)
+ * @ret n ANSI escape sequence numeric portion, or 0 for none
+ */
+#define KEY_ANSI_N( key ) ( ( ( (key) >> 8 ) & 0xff ) - 1 )
+
+/**
+ * Extract ANSI escape sequence terminating character
+ *
+ * @v key Key value (or relative key value)
+ * @ret terminator ANSI escape sequence terminating character
+ */
#define KEY_ANSI_TERMINATOR( key ) ( (key) & 0xff )
-#define KEY_MIN 0x101
#define KEY_UP KEY_ANSI ( 0, 'A' ) /**< Up arrow */
#define KEY_DOWN KEY_ANSI ( 0, 'B' ) /**< Down arrow */
#define KEY_RIGHT KEY_ANSI ( 0, 'C' ) /**< Right arrow */
diff --git a/src/include/ipxe/netdevice.h b/src/include/ipxe/netdevice.h
index af932c25..caa83b44 100644
--- a/src/include/ipxe/netdevice.h
+++ b/src/include/ipxe/netdevice.h
@@ -473,22 +473,27 @@ struct net_device {
struct net_driver {
/** Name */
const char *name;
+ /** Size of private data */
+ size_t priv_len;
/** Probe device
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
- int ( * probe ) ( struct net_device *netdev );
+ int ( * probe ) ( struct net_device *netdev, void *priv );
/** Notify of device or link state change
*
* @v netdev Network device
+ * @v priv Private data
*/
- void ( * notify ) ( struct net_device *netdev );
+ void ( * notify ) ( struct net_device *netdev, void *priv );
/** Remove device
*
* @v netdev Network device
+ * @v priv Private data
*/
- void ( * remove ) ( struct net_device *netdev );
+ void ( * remove ) ( struct net_device *netdev, void *priv );
};
/** Network driver table */
@@ -569,17 +574,6 @@ netdev_put ( struct net_device *netdev ) {
}
/**
- * Get driver private area for this network device
- *
- * @v netdev Network device
- * @ret priv Driver private area for this network device
- */
-static inline __attribute__ (( always_inline )) void *
-netdev_priv ( struct net_device *netdev ) {
- return netdev->priv;
-}
-
-/**
* Get per-netdevice configuration settings block
*
* @v netdev Network device
@@ -699,6 +693,8 @@ netdev_rx_frozen ( struct net_device *netdev ) {
return ( netdev->state & NETDEV_RX_FROZEN );
}
+extern void * netdev_priv ( struct net_device *netdev,
+ struct net_driver *driver );
extern void netdev_rx_freeze ( struct net_device *netdev );
extern void netdev_rx_unfreeze ( struct net_device *netdev );
extern void netdev_link_err ( struct net_device *netdev, int rc );
diff --git a/src/include/usr/shimmgmt.h b/src/include/usr/shimmgmt.h
new file mode 100644
index 00000000..0c59f54a
--- /dev/null
+++ b/src/include/usr/shimmgmt.h
@@ -0,0 +1,17 @@
+#ifndef _USR_SHIMMGMT_H
+#define _USR_SHIMMGMT_H
+
+/** @file
+ *
+ * EFI shim management
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <ipxe/image.h>
+
+extern int shim ( struct image *image, int require_loader, int allow_pxe,
+ int allow_sbat );
+
+#endif /* _USR_SHIMMGMT_H */
diff --git a/src/interface/efi/efi_debug.c b/src/interface/efi/efi_debug.c
index 967bb618..1372776f 100644
--- a/src/interface/efi/efi_debug.c
+++ b/src/interface/efi/efi_debug.c
@@ -47,12 +47,30 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
static EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *efidpt;
EFI_REQUEST_PROTOCOL ( EFI_DEVICE_PATH_TO_TEXT_PROTOCOL, &efidpt );
-/** Iscsi4Dxe module GUID */
+/** HttpBootDxe module GUID */
+static EFI_GUID efi_http_boot_dxe_guid = {
+ 0xecebcb00, 0xd9c8, 0x11e4,
+ { 0xaf, 0x3d, 0x8c, 0xdc, 0xd4, 0x26, 0xc9, 0x73 }
+};
+
+/** IScsiDxe module GUID */
+static EFI_GUID efi_iscsi_dxe_guid = {
+ 0x86cddf93, 0x4872, 0x4597,
+ { 0x8a, 0xf9, 0xa3, 0x5a, 0xe4, 0xd3, 0x72, 0x5f }
+};
+
+/** Old IScsi4Dxe module GUID */
static EFI_GUID efi_iscsi4_dxe_guid = {
0x4579b72d, 0x7ec4, 0x4dd4,
{ 0x84, 0x86, 0x08, 0x3c, 0x86, 0xb1, 0x82, 0xa7 }
};
+/** UefiPxeBcDxe module GUID */
+static EFI_GUID efi_uefi_pxe_bc_dxe_guid = {
+ 0xb95e9fda, 0x26de, 0x48d2,
+ { 0x88, 0x07, 0x1f, 0x91, 0x07, 0xac, 0x5e, 0x3a }
+};
+
/** VlanConfigDxe module GUID */
static EFI_GUID efi_vlan_config_dxe_guid = {
0xe4f61863, 0xfe2c, 0x4b56,
@@ -99,20 +117,48 @@ static struct efi_well_known_guid efi_well_known_guids[] = {
"Dhcp4" },
{ &efi_dhcp4_service_binding_protocol_guid,
"Dhcp4Sb" },
+ { &efi_dhcp6_protocol_guid,
+ "Dhcp6" },
+ { &efi_dhcp6_service_binding_protocol_guid,
+ "Dhcp6Sb" },
{ &efi_disk_io_protocol_guid,
"DiskIo" },
+ { &efi_dns4_protocol_guid,
+ "Dns4" },
+ { &efi_dns4_service_binding_protocol_guid,
+ "Dns4Sb" },
+ { &efi_dns6_protocol_guid,
+ "Dns6" },
+ { &efi_dns6_service_binding_protocol_guid,
+ "Dns6Sb" },
{ &efi_graphics_output_protocol_guid,
"GraphicsOutput" },
{ &efi_hii_config_access_protocol_guid,
"HiiConfigAccess" },
{ &efi_hii_font_protocol_guid,
"HiiFont" },
+ { &efi_http_boot_dxe_guid,
+ "HttpBootDxe" },
+ { &efi_http_protocol_guid,
+ "Http" },
+ { &efi_http_service_binding_protocol_guid,
+ "HttpSb" },
{ &efi_ip4_protocol_guid,
"Ip4" },
{ &efi_ip4_config_protocol_guid,
"Ip4Config" },
+ { &efi_ip4_config2_protocol_guid,
+ "Ip4Config2" },
{ &efi_ip4_service_binding_protocol_guid,
"Ip4Sb" },
+ { &efi_ip6_protocol_guid,
+ "Ip6" },
+ { &efi_ip6_config_protocol_guid,
+ "Ip6Config" },
+ { &efi_ip6_service_binding_protocol_guid,
+ "Ip6Sb" },
+ { &efi_iscsi_dxe_guid,
+ "IScsiDxe" },
{ &efi_iscsi4_dxe_guid,
"IScsi4Dxe" },
{ &efi_load_file_protocol_guid,
@@ -131,6 +177,10 @@ static struct efi_well_known_guid efi_well_known_guids[] = {
"Mtftp4" },
{ &efi_mtftp4_service_binding_protocol_guid,
"Mtftp4Sb" },
+ { &efi_mtftp6_protocol_guid,
+ "Mtftp6" },
+ { &efi_mtftp6_service_binding_protocol_guid,
+ "Mtftp6Sb" },
{ &efi_nii_protocol_guid,
"Nii" },
{ &efi_nii31_protocol_guid,
@@ -143,6 +193,8 @@ static struct efi_well_known_guid efi_well_known_guids[] = {
"PxeBaseCode" },
{ &efi_serial_io_protocol_guid,
"SerialIo" },
+ { &efi_shim_lock_protocol_guid,
+ "ShimLock" },
{ &efi_simple_file_system_protocol_guid,
"SimpleFileSystem" },
{ &efi_simple_network_protocol_guid,
@@ -161,12 +213,22 @@ static struct efi_well_known_guid efi_well_known_guids[] = {
"Tcp4" },
{ &efi_tcp4_service_binding_protocol_guid,
"Tcp4Sb" },
+ { &efi_tcp6_protocol_guid,
+ "Tcp6" },
+ { &efi_tcp6_service_binding_protocol_guid,
+ "Tcp6Sb" },
{ &efi_tree_protocol_guid,
"TrEE" },
{ &efi_udp4_protocol_guid,
"Udp4" },
{ &efi_udp4_service_binding_protocol_guid,
"Udp4Sb" },
+ { &efi_udp6_protocol_guid,
+ "Udp6" },
+ { &efi_udp6_service_binding_protocol_guid,
+ "Udp6Sb" },
+ { &efi_uefi_pxe_bc_dxe_guid,
+ "UefiPxeBcDxe" },
{ &efi_uga_draw_protocol_guid,
"UgaDraw" },
{ &efi_unicode_collation_protocol_guid,
@@ -325,6 +387,34 @@ void dbg_efi_openers ( EFI_HANDLE handle, EFI_GUID *protocol ) {
}
/**
+ * Print protocol information on a given handle
+ *
+ * @v handle EFI handle
+ * @v protocol Protocol GUID
+ */
+void dbg_efi_protocol ( EFI_HANDLE handle, EFI_GUID *protocol ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ VOID *interface;
+ EFI_STATUS efirc;
+ int rc;
+
+ /* Get protocol instance */
+ if ( ( efirc = bs->HandleProtocol ( handle, protocol,
+ &interface ) ) != 0 ) {
+ rc = -EEFI ( efirc );
+ printf ( "HANDLE %s could not identify %s: %s\n",
+ efi_handle_name ( handle ),
+ efi_guid_ntoa ( protocol ), strerror ( rc ) );
+ return;
+ }
+ printf ( "HANDLE %s %s at %p\n", efi_handle_name ( handle ),
+ efi_guid_ntoa ( protocol ), interface );
+
+ /* Dump list of openers */
+ dbg_efi_openers ( handle, protocol );
+}
+
+/**
* Print list of protocol handlers attached to a handle
*
* @v handle EFI handle
@@ -332,7 +422,6 @@ void dbg_efi_openers ( EFI_HANDLE handle, EFI_GUID *protocol ) {
void dbg_efi_protocols ( EFI_HANDLE handle ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_GUID **protocols;
- EFI_GUID *protocol;
UINTN count;
unsigned int i;
EFI_STATUS efirc;
@@ -355,10 +444,7 @@ void dbg_efi_protocols ( EFI_HANDLE handle ) {
/* Dump list of protocols */
for ( i = 0 ; i < count ; i++ ) {
- protocol = protocols[i];
- printf ( "HANDLE %s %s supported\n", efi_handle_name ( handle ),
- efi_guid_ntoa ( protocol ) );
- dbg_efi_openers ( handle, protocol );
+ dbg_efi_protocol ( handle, protocols[i] );
}
/* Free list */
diff --git a/src/interface/efi/efi_file.c b/src/interface/efi/efi_file.c
index b232591d..2ae3a0cb 100644
--- a/src/interface/efi/efi_file.c
+++ b/src/interface/efi/efi_file.c
@@ -250,6 +250,10 @@ static size_t efi_file_read_initrd ( struct efi_file_reader *reader ) {
len = 0;
for_each_image ( image ) {
+ /* Skip hidden images */
+ if ( image->flags & IMAGE_HIDDEN )
+ continue;
+
/* Pad to alignment boundary */
pad_len = ( ( -reader->pos ) & ( INITRD_ALIGN - 1 ) );
if ( pad_len ) {
@@ -291,10 +295,12 @@ static size_t efi_file_read_initrd ( struct efi_file_reader *reader ) {
* Open fixed file
*
* @v file EFI file
+ * @v wname Filename
* @v new New EFI file
* @ret efirc EFI status code
*/
static EFI_STATUS efi_file_open_fixed ( struct efi_file *file,
+ const wchar_t *wname,
EFI_FILE_PROTOCOL **new ) {
/* Increment reference count */
@@ -303,7 +309,8 @@ static EFI_STATUS efi_file_open_fixed ( struct efi_file *file,
/* Return opened file */
*new = &file->file;
- DBGC ( file, "EFIFILE %s opened\n", efi_file_name ( file ) );
+ DBGC ( file, "EFIFILE %s opened via %ls\n",
+ efi_file_name ( file ), wname );
return 0;
}
@@ -321,6 +328,36 @@ static void efi_file_image ( struct efi_file *file, struct image *image ) {
}
/**
+ * Open image-backed file
+ *
+ * @v image Image
+ * @v wname Filename
+ * @v new New EFI file
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS efi_file_open_image ( struct image *image,
+ const wchar_t *wname,
+ EFI_FILE_PROTOCOL **new ) {
+ struct efi_file *file;
+
+ /* Allocate and initialise file */
+ file = zalloc ( sizeof ( *file ) );
+ if ( ! file )
+ return EFI_OUT_OF_RESOURCES;
+ ref_init ( &file->refcnt, efi_file_free );
+ memcpy ( &file->file, &efi_file_root.file, sizeof ( file->file ) );
+ memcpy ( &file->load, &efi_file_root.load, sizeof ( file->load ) );
+ efi_file_image ( file, image_get ( image ) );
+
+ /* Return opened file */
+ *new = &file->file;
+
+ DBGC ( file, "EFIFILE %s opened via %ls\n",
+ efi_file_name ( file ), wname );
+ return 0;
+}
+
+/**
* Open file
*
* @v this EFI file
@@ -335,9 +372,9 @@ efi_file_open ( EFI_FILE_PROTOCOL *this, EFI_FILE_PROTOCOL **new,
CHAR16 *wname, UINT64 mode, UINT64 attributes __unused ) {
struct efi_file *file = container_of ( this, struct efi_file, file );
char buf[ wcslen ( wname ) + 1 /* NUL */ ];
- struct efi_file *new_file;
struct image *image;
char *name;
+ char *sep;
/* Convert name to ASCII */
snprintf ( buf, sizeof ( buf ), "%ls", wname );
@@ -351,7 +388,7 @@ efi_file_open ( EFI_FILE_PROTOCOL *this, EFI_FILE_PROTOCOL **new,
/* Allow root directory itself to be opened */
if ( ( name[0] == '\0' ) || ( name[0] == '.' ) )
- return efi_file_open_fixed ( &efi_file_root, new );
+ return efi_file_open_fixed ( &efi_file_root, wname, new );
/* Fail unless opening from the root */
if ( file != &efi_file_root ) {
@@ -367,31 +404,28 @@ efi_file_open ( EFI_FILE_PROTOCOL *this, EFI_FILE_PROTOCOL **new,
return EFI_WRITE_PROTECTED;
}
- /* Allow magic initrd to be opened */
- if ( strcasecmp ( name, efi_file_initrd.file.name ) == 0 )
- return efi_file_open_fixed ( &efi_file_initrd.file, new );
+ /* Allow registered images to be opened */
+ if ( ( image = efi_file_find ( name ) ) != NULL )
+ return efi_file_open_image ( image, wname, new );
- /* Identify image */
- image = efi_file_find ( name );
- if ( ! image ) {
- DBGC ( file, "EFIFILE %s does not exist\n", name );
- return EFI_NOT_FOUND;
+ /* Allow magic initrd to be opened */
+ if ( strcasecmp ( name, efi_file_initrd.file.name ) == 0 ) {
+ return efi_file_open_fixed ( &efi_file_initrd.file, wname,
+ new );
}
- /* Allocate and initialise file */
- new_file = zalloc ( sizeof ( *new_file ) );
- if ( ! new_file )
- return EFI_OUT_OF_RESOURCES;
- ref_init ( &file->refcnt, efi_file_free );
- memcpy ( &new_file->file, &efi_file_root.file,
- sizeof ( new_file->file ) );
- memcpy ( &new_file->load, &efi_file_root.load,
- sizeof ( new_file->load ) );
- efi_file_image ( new_file, image_get ( image ) );
- *new = &new_file->file;
- DBGC ( new_file, "EFIFILE %s opened\n", efi_file_name ( new_file ) );
+ /* Allow currently selected image to be opened as "grub*.efi",
+ * to work around buggy versions of the UEFI shim.
+ */
+ if ( ( strncasecmp ( name, "grub", 4 ) == 0 ) &&
+ ( ( sep = strrchr ( name, '.' ) ) != NULL ) &&
+ ( strcasecmp ( sep, ".efi" ) == 0 ) &&
+ ( ( image = find_image_tag ( &selected_image ) ) != NULL ) ) {
+ return efi_file_open_image ( image, wname, new );
+ }
- return 0;
+ DBGC ( file, "EFIFILE %ls does not exist\n", wname );
+ return EFI_NOT_FOUND;
}
/**
@@ -505,13 +539,21 @@ static EFI_STATUS efi_file_read_dir ( struct efi_file *file, UINTN *len,
/* Construct directory entries for image-backed files */
index = file->pos;
for_each_image ( image ) {
- if ( index-- == 0 ) {
- efi_file_image ( &entry, image );
- efirc = efi_file_info ( &entry, len, data );
- if ( efirc == 0 )
- file->pos++;
- return efirc;
- }
+
+ /* Skip hidden images */
+ if ( image->flags & IMAGE_HIDDEN )
+ continue;
+
+ /* Skip preceding images */
+ if ( index-- )
+ continue;
+
+ /* Construct directory entry */
+ efi_file_image ( &entry, image );
+ efirc = efi_file_info ( &entry, len, data );
+ if ( efirc == 0 )
+ file->pos++;
+ return efirc;
}
/* No more entries */
@@ -821,7 +863,7 @@ efi_file_open_volume ( EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *filesystem __unused,
EFI_FILE_PROTOCOL **file ) {
DBGC ( &efi_file_root, "EFIFILE open volume\n" );
- return efi_file_open_fixed ( &efi_file_root, file );
+ return efi_file_open_fixed ( &efi_file_root, L"<volume>", file );
}
/** EFI simple file system protocol */
@@ -1074,6 +1116,7 @@ int efi_file_install ( EFI_HANDLE handle ) {
EFI_DISK_IO_PROTOCOL *diskio;
void *interface;
} diskio;
+ struct image *image;
EFI_STATUS efirc;
int rc;
@@ -1137,9 +1180,12 @@ int efi_file_install ( EFI_HANDLE handle ) {
goto err_initrd_claim;
/* Install Linux initrd fixed device path file if non-empty */
- if ( have_images() &&
- ( ( rc = efi_file_path_install ( &efi_file_initrd ) ) != 0 ) ) {
- goto err_initrd_install;
+ for_each_image ( image ) {
+ if ( image->flags & IMAGE_HIDDEN )
+ continue;
+ if ( ( rc = efi_file_path_install ( &efi_file_initrd ) ) != 0 )
+ goto err_initrd_install;
+ break;
}
return 0;
diff --git a/src/interface/efi/efi_guid.c b/src/interface/efi/efi_guid.c
index 663585dc..f841448f 100644
--- a/src/interface/efi/efi_guid.c
+++ b/src/interface/efi/efi_guid.c
@@ -37,23 +37,32 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/efi/Protocol/DevicePath.h>
#include <ipxe/efi/Protocol/DevicePathToText.h>
#include <ipxe/efi/Protocol/Dhcp4.h>
+#include <ipxe/efi/Protocol/Dhcp6.h>
#include <ipxe/efi/Protocol/DiskIo.h>
+#include <ipxe/efi/Protocol/Dns4.h>
+#include <ipxe/efi/Protocol/Dns6.h>
#include <ipxe/efi/Protocol/DriverBinding.h>
#include <ipxe/efi/Protocol/GraphicsOutput.h>
#include <ipxe/efi/Protocol/HiiConfigAccess.h>
#include <ipxe/efi/Protocol/HiiFont.h>
+#include <ipxe/efi/Protocol/Http.h>
#include <ipxe/efi/Protocol/Ip4.h>
#include <ipxe/efi/Protocol/Ip4Config.h>
+#include <ipxe/efi/Protocol/Ip4Config2.h>
+#include <ipxe/efi/Protocol/Ip6.h>
+#include <ipxe/efi/Protocol/Ip6Config.h>
#include <ipxe/efi/Protocol/LoadFile.h>
#include <ipxe/efi/Protocol/LoadFile2.h>
#include <ipxe/efi/Protocol/LoadedImage.h>
#include <ipxe/efi/Protocol/ManagedNetwork.h>
#include <ipxe/efi/Protocol/Mtftp4.h>
+#include <ipxe/efi/Protocol/Mtftp6.h>
#include <ipxe/efi/Protocol/NetworkInterfaceIdentifier.h>
#include <ipxe/efi/Protocol/PciIo.h>
#include <ipxe/efi/Protocol/PciRootBridgeIo.h>
#include <ipxe/efi/Protocol/PxeBaseCode.h>
#include <ipxe/efi/Protocol/SerialIo.h>
+#include <ipxe/efi/Protocol/ShimLock.h>
#include <ipxe/efi/Protocol/SimpleFileSystem.h>
#include <ipxe/efi/Protocol/SimpleNetwork.h>
#include <ipxe/efi/Protocol/SimplePointer.h>
@@ -62,7 +71,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/efi/Protocol/SimpleTextOut.h>
#include <ipxe/efi/Protocol/TcgService.h>
#include <ipxe/efi/Protocol/Tcp4.h>
+#include <ipxe/efi/Protocol/Tcp6.h>
#include <ipxe/efi/Protocol/Udp4.h>
+#include <ipxe/efi/Protocol/Udp6.h>
#include <ipxe/efi/Protocol/UgaDraw.h>
#include <ipxe/efi/Protocol/UnicodeCollation.h>
#include <ipxe/efi/Protocol/UsbHostController.h>
@@ -139,10 +150,34 @@ EFI_GUID efi_dhcp4_protocol_guid
EFI_GUID efi_dhcp4_service_binding_protocol_guid
= EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID;
+/** DHCPv6 protocol GUID */
+EFI_GUID efi_dhcp6_protocol_guid
+ = EFI_DHCP6_PROTOCOL_GUID;
+
+/** DHCPv6 service binding protocol GUID */
+EFI_GUID efi_dhcp6_service_binding_protocol_guid
+ = EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID;
+
/** Disk I/O protocol GUID */
EFI_GUID efi_disk_io_protocol_guid
= EFI_DISK_IO_PROTOCOL_GUID;
+/** DNSv4 protocol GUID */
+EFI_GUID efi_dns4_protocol_guid
+ = EFI_DNS4_PROTOCOL_GUID;
+
+/** DNSv4 service binding protocol GUID */
+EFI_GUID efi_dns4_service_binding_protocol_guid
+ = EFI_DNS4_SERVICE_BINDING_PROTOCOL_GUID;
+
+/** DNSv6 protocol GUID */
+EFI_GUID efi_dns6_protocol_guid
+ = EFI_DNS6_PROTOCOL_GUID;
+
+/** DNSv6 service binding protocol GUID */
+EFI_GUID efi_dns6_service_binding_protocol_guid
+ = EFI_DNS6_SERVICE_BINDING_PROTOCOL_GUID;
+
/** Driver binding protocol GUID */
EFI_GUID efi_driver_binding_protocol_guid
= EFI_DRIVER_BINDING_PROTOCOL_GUID;
@@ -159,6 +194,14 @@ EFI_GUID efi_hii_config_access_protocol_guid
EFI_GUID efi_hii_font_protocol_guid
= EFI_HII_FONT_PROTOCOL_GUID;
+/** HTTP protocol GUID */
+EFI_GUID efi_http_protocol_guid
+ = EFI_HTTP_PROTOCOL_GUID;
+
+/** HTTP service binding protocol GUID */
+EFI_GUID efi_http_service_binding_protocol_guid
+ = EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID;
+
/** IPv4 protocol GUID */
EFI_GUID efi_ip4_protocol_guid
= EFI_IP4_PROTOCOL_GUID;
@@ -167,10 +210,26 @@ EFI_GUID efi_ip4_protocol_guid
EFI_GUID efi_ip4_config_protocol_guid
= EFI_IP4_CONFIG_PROTOCOL_GUID;
+/** IPv4 configuration 2 protocol GUID */
+EFI_GUID efi_ip4_config2_protocol_guid
+ = EFI_IP4_CONFIG2_PROTOCOL_GUID;
+
/** IPv4 service binding protocol GUID */
EFI_GUID efi_ip4_service_binding_protocol_guid
= EFI_IP4_SERVICE_BINDING_PROTOCOL_GUID;
+/** IPv6 protocol GUID */
+EFI_GUID efi_ip6_protocol_guid
+ = EFI_IP6_PROTOCOL_GUID;
+
+/** IPv6 configuration protocol GUID */
+EFI_GUID efi_ip6_config_protocol_guid
+ = EFI_IP6_CONFIG_PROTOCOL_GUID;
+
+/** IPv6 service binding protocol GUID */
+EFI_GUID efi_ip6_service_binding_protocol_guid
+ = EFI_IP6_SERVICE_BINDING_PROTOCOL_GUID;
+
/** Load file protocol GUID */
EFI_GUID efi_load_file_protocol_guid
= EFI_LOAD_FILE_PROTOCOL_GUID;
@@ -203,6 +262,14 @@ EFI_GUID efi_mtftp4_protocol_guid
EFI_GUID efi_mtftp4_service_binding_protocol_guid
= EFI_MTFTP4_SERVICE_BINDING_PROTOCOL_GUID;
+/** MTFTPv6 protocol GUID */
+EFI_GUID efi_mtftp6_protocol_guid
+ = EFI_MTFTP6_PROTOCOL_GUID;
+
+/** MTFTPv6 service binding protocol GUID */
+EFI_GUID efi_mtftp6_service_binding_protocol_guid
+ = EFI_MTFTP6_SERVICE_BINDING_PROTOCOL_GUID;
+
/** Network interface identifier protocol GUID (old version) */
EFI_GUID efi_nii_protocol_guid
= EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID;
@@ -227,6 +294,10 @@ EFI_GUID efi_pxe_base_code_protocol_guid
EFI_GUID efi_serial_io_protocol_guid
= EFI_SERIAL_IO_PROTOCOL_GUID;
+/** Shim lock protocol GUID */
+EFI_GUID efi_shim_lock_protocol_guid
+ = EFI_SHIM_LOCK_PROTOCOL_GUID;
+
/** Simple file system protocol GUID */
EFI_GUID efi_simple_file_system_protocol_guid
= EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
@@ -263,6 +334,14 @@ EFI_GUID efi_tcp4_protocol_guid
EFI_GUID efi_tcp4_service_binding_protocol_guid
= EFI_TCP4_SERVICE_BINDING_PROTOCOL_GUID;
+/** TCPv6 protocol GUID */
+EFI_GUID efi_tcp6_protocol_guid
+ = EFI_TCP6_PROTOCOL_GUID;
+
+/** TCPv6 service binding protocol GUID */
+EFI_GUID efi_tcp6_service_binding_protocol_guid
+ = EFI_TCP6_SERVICE_BINDING_PROTOCOL_GUID;
+
/** TrEE protocol GUID */
EFI_GUID efi_tree_protocol_guid
= EFI_TREE_PROTOCOL_GUID;
@@ -275,6 +354,14 @@ EFI_GUID efi_udp4_protocol_guid
EFI_GUID efi_udp4_service_binding_protocol_guid
= EFI_UDP4_SERVICE_BINDING_PROTOCOL_GUID;
+/** UDPv6 protocol GUID */
+EFI_GUID efi_udp6_protocol_guid
+ = EFI_UDP6_PROTOCOL_GUID;
+
+/** UDPv6 service binding protocol GUID */
+EFI_GUID efi_udp6_service_binding_protocol_guid
+ = EFI_UDP6_SERVICE_BINDING_PROTOCOL_GUID;
+
/** UGA draw protocol GUID */
EFI_GUID efi_uga_draw_protocol_guid
= EFI_UGA_DRAW_PROTOCOL_GUID;
diff --git a/src/interface/efi/efi_settings.c b/src/interface/efi/efi_settings.c
new file mode 100644
index 00000000..cde0ff8d
--- /dev/null
+++ b/src/interface/efi/efi_settings.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2023 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+/**
+ * @file
+ *
+ * EFI variable settings
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/settings.h>
+#include <ipxe/init.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/efi_strings.h>
+
+/** EFI variable settings scope */
+static const struct settings_scope efivars_scope;
+
+/** EFI variable settings */
+static struct settings efivars;
+
+/**
+ * Check applicability of EFI variable setting
+ *
+ * @v settings Settings block
+ * @v setting Setting
+ * @ret applies Setting applies within this settings block
+ */
+static int efivars_applies ( struct settings *settings __unused,
+ const struct setting *setting ) {
+
+ return ( setting->scope == &efivars_scope );
+}
+
+/**
+ * Find first matching EFI variable name
+ *
+ * @v wname Name
+ * @v guid GUID to fill in
+ * @ret rc Return status code
+ */
+static int efivars_find ( const CHAR16 *wname, EFI_GUID *guid ) {
+ EFI_RUNTIME_SERVICES *rs = efi_systab->RuntimeServices;
+ size_t wname_len = ( ( wcslen ( wname ) + 1 ) * sizeof ( wname[0] ) );
+ CHAR16 *buf;
+ CHAR16 *tmp;
+ UINTN size;
+ EFI_STATUS efirc;
+ int rc;
+
+ /* Allocate single wNUL for first call to GetNextVariableName() */
+ size = sizeof ( buf[0] );
+ buf = zalloc ( size );
+ if ( ! buf )
+ return -ENOMEM;
+
+ /* Iterate over all veriables */
+ while ( 1 ) {
+
+ /* Get next variable name */
+ efirc = rs->GetNextVariableName ( &size, buf, guid );
+ if ( efirc == EFI_BUFFER_TOO_SMALL ) {
+ tmp = realloc ( buf, size );
+ if ( ! tmp ) {
+ rc = -ENOMEM;
+ break;
+ }
+ buf = tmp;
+ efirc = rs->GetNextVariableName ( &size, buf, guid );
+ }
+ if ( efirc == EFI_NOT_FOUND ) {
+ rc = -ENOENT;
+ break;
+ }
+ if ( efirc != 0 ) {
+ rc = -EEFI ( efirc );
+ DBGC ( &efivars, "EFIVARS %s:%ls could not fetch next "
+ "variable name: %s\n",
+ efi_guid_ntoa ( guid ), buf, strerror ( rc ) );
+ break;
+ }
+ DBGC2 ( &efivars, "EFIVARS %s:%ls exists\n",
+ efi_guid_ntoa ( guid ), buf );
+
+ /* Check for matching variable name */
+ if ( memcmp ( wname, buf, wname_len ) == 0 ) {
+ rc = 0;
+ break;
+ }
+ }
+
+ /* Free temporary buffer */
+ free ( buf );
+
+ return rc;
+}
+
+/**
+ * Fetch value of EFI variable setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to fetch
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ */
+static int efivars_fetch ( struct settings *settings __unused,
+ struct setting *setting, void *data, size_t len ) {
+ EFI_RUNTIME_SERVICES *rs = efi_systab->RuntimeServices;
+ size_t name_len = strlen ( setting->name );
+ CHAR16 wname[ name_len + 1 /* wNUL */ ];
+ EFI_GUID guid;
+ UINT32 attrs;
+ UINTN size;
+ void *buf;
+ EFI_STATUS efirc;
+ int rc;
+
+ /* Convert name to UCS-2 */
+ efi_snprintf ( wname, sizeof ( wname ), "%s", setting->name );
+
+ /* Find variable GUID */
+ if ( ( rc = efivars_find ( wname, &guid ) ) != 0 )
+ goto err_find;
+
+ /* Get variable length */
+ size = 0;
+ if ( ( efirc = rs->GetVariable ( wname, &guid, &attrs, &size,
+ NULL ) != EFI_BUFFER_TOO_SMALL ) ) {
+ rc = -EEFI ( efirc );
+ DBGC ( &efivars, "EFIVARS %s:%ls could not get size: %s\n",
+ efi_guid_ntoa ( &guid ), wname, strerror ( rc ) );
+ goto err_len;
+ }
+
+ /* Allocate temporary buffer, since GetVariable() is not
+ * guaranteed to return partial data for an underlength
+ * buffer.
+ */
+ buf = malloc ( size );
+ if ( ! buf ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+
+ /* Get variable value */
+ if ( ( efirc = rs->GetVariable ( wname, &guid, &attrs, &size,
+ buf ) ) != 0 ) {
+ rc = -EEFI ( efirc );
+ DBGC ( &efivars, "EFIVARS %s:%ls could not get %zd bytes: "
+ "%s\n", efi_guid_ntoa ( &guid ), wname,
+ ( ( size_t ) size ), strerror ( rc ) );
+ goto err_get;
+ }
+ DBGC ( &efivars, "EFIVARS %s:%ls:\n", efi_guid_ntoa ( &guid ), wname );
+ DBGC_HDA ( &efivars, 0, buf, size );
+
+ /* Return setting value */
+ if ( len > size )
+ len = size;
+ memcpy ( data, buf, len );
+ if ( ! setting->type )
+ setting->type = &setting_type_hex;
+
+ /* Free temporary buffer */
+ free ( buf );
+
+ return size;
+
+ err_get:
+ free ( buf );
+ err_alloc:
+ err_len:
+ err_find:
+ return rc;
+}
+
+/** EFI variable settings operations */
+static struct settings_operations efivars_operations = {
+ .applies = efivars_applies,
+ .fetch = efivars_fetch,
+};
+
+/** EFI variable settings */
+static struct settings efivars = {
+ .refcnt = NULL,
+ .siblings = LIST_HEAD_INIT ( efivars.siblings ),
+ .children = LIST_HEAD_INIT ( efivars.children ),
+ .op = &efivars_operations,
+ .default_scope = &efivars_scope,
+};
+
+/**
+ * Initialise EFI variable settings
+ *
+ */
+static void efivars_init ( void ) {
+ int rc;
+
+ /* Register settings block */
+ if ( ( rc = register_settings ( &efivars, NULL, "efi" ) ) != 0 ) {
+ DBGC ( &efivars, "EFIVARS could not register: %s\n",
+ strerror ( rc ) );
+ return;
+ }
+}
+
+/** EFI variable settings initialiser */
+struct init_fn efivars_init_fn __init_fn ( INIT_NORMAL ) = {
+ .initialise = efivars_init,
+};
diff --git a/src/interface/efi/efi_shim.c b/src/interface/efi/efi_shim.c
new file mode 100644
index 00000000..a46d79d0
--- /dev/null
+++ b/src/interface/efi/efi_shim.c
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2022 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ipxe/image.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/efi_strings.h>
+#include <ipxe/efi/efi_shim.h>
+#include <ipxe/efi/Protocol/PxeBaseCode.h>
+#include <ipxe/efi/Protocol/ShimLock.h>
+
+/** @file
+ *
+ * UEFI shim special handling
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+/**
+ * Require use of a third party loader binary
+ *
+ * The UEFI shim is gradually becoming less capable of directly
+ * executing a Linux kernel image, due to an ever increasing list of
+ * assumptions that it will only ever be used in conjunction with a
+ * second stage loader binary such as GRUB.
+ *
+ * For example: shim will erroneously complain if the image that it
+ * loads and executes does not in turn call in to the "shim lock
+ * protocol" to verify a separate newly loaded binary before calling
+ * ExitBootServices(), even if no such separate binary is used or
+ * required.
+ *
+ * Experience shows that there is unfortunately no point in trying to
+ * get a fix for this upstreamed into shim. We therefore default to
+ * reducing the Secure Boot attack surface by removing, where
+ * possible, this spurious requirement for the use of an additional
+ * second stage loader.
+ *
+ * This option may be used to require the use of an additional second
+ * stage loader binary, in case this behaviour is ever desirable.
+ */
+int efi_shim_require_loader = 0;
+
+/**
+ * Allow use of PXE base code protocol
+ *
+ * We provide shim with access to all of the relevant downloaded files
+ * via our EFI_SIMPLE_FILE_SYSTEM_PROTOCOL interface. However, shim
+ * will instead try to redownload the files via TFTP since it prefers
+ * to use the EFI_PXE_BASE_CODE_PROTOCOL installed on the same handle.
+ *
+ * Experience shows that there is unfortunately no point in trying to
+ * get a fix for this upstreamed into shim. We therefore default to
+ * working around this undesirable behaviour by stopping the PXE base
+ * code protocol before invoking shim.
+ *
+ * This option may be used to allow shim to use the PXE base code
+ * protocol, in case this behaviour is ever desirable.
+ */
+int efi_shim_allow_pxe = 0;
+
+/**
+ * Allow SBAT variable access
+ *
+ * The UEFI shim implements a fairly nicely designed revocation
+ * mechanism designed around the concept of security generations.
+ * Unfortunately nobody in the shim community has thus far added the
+ * relevant metadata to the Linux kernel, with the result that current
+ * versions of shim are incapable of booting current versions of the
+ * Linux kernel.
+ *
+ * Experience shows that there is unfortunately no point in trying to
+ * get a fix for this upstreamed into shim. We therefore default to
+ * working around this undesirable behaviour by patching data read
+ * from the "SbatLevel" variable used to hold SBAT configuration.
+ *
+ * This option may be used to allow shim unpatched access to the
+ * "SbatLevel" variable, in case this behaviour is ever desirable.
+ */
+int efi_shim_allow_sbat = 0;
+
+/** UEFI shim image */
+struct image_tag efi_shim __image_tag = {
+ .name = "SHIM",
+};
+
+/** Original GetMemoryMap() function */
+static EFI_GET_MEMORY_MAP efi_shim_orig_get_memory_map;
+
+/** Original ExitBootServices() function */
+static EFI_EXIT_BOOT_SERVICES efi_shim_orig_exit_boot_services;
+
+/** Original SetVariable() function */
+static EFI_SET_VARIABLE efi_shim_orig_set_variable;
+
+/** Original GetVariable() function */
+static EFI_GET_VARIABLE efi_shim_orig_get_variable;
+
+/** Verify read from SbatLevel variable */
+static int efi_shim_sbatlevel_verify;
+
+/**
+ * Check if variable is SbatLevel
+ *
+ * @v name Variable name
+ * @v guid Variable namespace GUID
+ * @ret is_sbatlevel Variable is SbatLevel
+ */
+static int efi_shim_is_sbatlevel ( const CHAR16 *name, const EFI_GUID *guid ) {
+ static CHAR16 sbatlevel[] = L"SbatLevel";
+ EFI_GUID *shimlock = &efi_shim_lock_protocol_guid;
+
+ return ( ( memcmp ( name, sbatlevel, sizeof ( sbatlevel ) ) == 0 ) &&
+ ( memcmp ( guid, shimlock, sizeof ( *shimlock ) ) == 0 ) );
+}
+
+/**
+ * Unlock UEFI shim
+ *
+ */
+static void efi_shim_unlock ( void ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ uint8_t empty[0];
+ union {
+ EFI_SHIM_LOCK_PROTOCOL *lock;
+ void *interface;
+ } u;
+ EFI_STATUS efirc;
+
+ /* Locate shim lock protocol */
+ if ( ( efirc = bs->LocateProtocol ( &efi_shim_lock_protocol_guid,
+ NULL, &u.interface ) ) == 0 ) {
+ u.lock->Verify ( empty, sizeof ( empty ) );
+ DBGC ( &efi_shim, "SHIM unlocked via %p\n", u.lock );
+ }
+}
+
+/**
+ * Wrap GetMemoryMap()
+ *
+ * @v len Memory map size
+ * @v map Memory map
+ * @v key Memory map key
+ * @v desclen Descriptor size
+ * @v descver Descriptor version
+ * @ret efirc EFI status code
+ */
+static EFIAPI EFI_STATUS efi_shim_get_memory_map ( UINTN *len,
+ EFI_MEMORY_DESCRIPTOR *map,
+ UINTN *key, UINTN *desclen,
+ UINT32 *descver ) {
+
+ /* Unlock shim */
+ if ( ! efi_shim_require_loader )
+ efi_shim_unlock();
+
+ /* Hand off to original GetMemoryMap() */
+ return efi_shim_orig_get_memory_map ( len, map, key, desclen,
+ descver );
+}
+
+/**
+ * Wrap ExitBootServices()
+ *
+ * @v handle Image handle
+ * @v key Memory map key
+ * @ret efirc EFI status code
+ */
+static EFIAPI EFI_STATUS efi_shim_exit_boot_services ( EFI_HANDLE handle,
+ UINTN key ) {
+ EFI_RUNTIME_SERVICES *rs = efi_systab->RuntimeServices;
+
+ /* Restore original runtime services functions */
+ rs->SetVariable = efi_shim_orig_set_variable;
+ rs->GetVariable = efi_shim_orig_get_variable;
+
+ /* Hand off to original ExitBootServices() */
+ return efi_shim_orig_exit_boot_services ( handle, key );
+}
+
+/**
+ * Wrap SetVariable()
+ *
+ * @v name Variable name
+ * @v guid Variable namespace GUID
+ * @v attrs Attributes
+ * @v len Buffer size
+ * @v data Data buffer
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_shim_set_variable ( CHAR16 *name, EFI_GUID *guid, UINT32 attrs,
+ UINTN len, VOID *data ) {
+ EFI_STATUS efirc;
+
+ /* Call original SetVariable() */
+ efirc = efi_shim_orig_set_variable ( name, guid, attrs, len, data );
+
+ /* Allow verification of SbatLevel variable content */
+ if ( efi_shim_is_sbatlevel ( name, guid ) && ( efirc == 0 ) ) {
+ DBGC ( &efi_shim, "SHIM detected write to %ls:\n", name );
+ DBGC_HDA ( &efi_shim, 0, data, len );
+ efi_shim_sbatlevel_verify = 1;
+ }
+
+ return efirc;
+}
+
+/**
+ * Wrap GetVariable()
+ *
+ * @v name Variable name
+ * @v guid Variable namespace GUID
+ * @v attrs Attributes to fill in
+ * @v len Buffer size
+ * @v data Data buffer
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_shim_get_variable ( CHAR16 *name, EFI_GUID *guid, UINT32 *attrs,
+ UINTN *len, VOID *data ) {
+ char *value = data;
+ EFI_STATUS efirc;
+
+ /* Call original GetVariable() */
+ efirc = efi_shim_orig_get_variable ( name, guid, attrs, len, data );
+
+ /* Patch SbatLevel variable if applicable */
+ if ( efi_shim_is_sbatlevel ( name, guid ) && data && ( efirc == 0 ) ) {
+ if ( efi_shim_allow_sbat ) {
+ DBGC ( &efi_shim, "SHIM allowing read from %ls:\n",
+ name );
+ } else if ( efi_shim_sbatlevel_verify ) {
+ DBGC ( &efi_shim, "SHIM allowing one read from %ls:\n",
+ name );
+ efi_shim_sbatlevel_verify = 0;
+ } else {
+ DBGC ( &efi_shim, "SHIM patching read from %ls:\n",
+ name );
+ value[0] = '\0';
+ }
+ DBGC_HDA ( &efi_shim, 0, data, *len );
+ }
+
+ return efirc;
+}
+
+/**
+ * Inhibit use of PXE base code
+ *
+ * @v handle EFI handle
+ * @ret rc Return status code
+ */
+static int efi_shim_inhibit_pxe ( EFI_HANDLE handle ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ union {
+ EFI_PXE_BASE_CODE_PROTOCOL *pxe;
+ void *interface;
+ } u;
+ EFI_STATUS efirc;
+ int rc;
+
+ /* Locate PXE base code */
+ if ( ( efirc = bs->OpenProtocol ( handle,
+ &efi_pxe_base_code_protocol_guid,
+ &u.interface, efi_image_handle, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
+ rc = -EEFI ( efirc );
+ DBGC ( &efi_shim, "SHIM could not open PXE base code: %s\n",
+ strerror ( rc ) );
+ goto err_no_base;
+ }
+
+ /* Stop PXE base code */
+ if ( ( efirc = u.pxe->Stop ( u.pxe ) ) != 0 ) {
+ rc = -EEFI ( efirc );
+ DBGC ( &efi_shim, "SHIM could not stop PXE base code: %s\n",
+ strerror ( rc ) );
+ goto err_stop;
+ }
+
+ /* Success */
+ rc = 0;
+ DBGC ( &efi_shim, "SHIM stopped PXE base code\n" );
+
+ err_stop:
+ bs->CloseProtocol ( handle, &efi_pxe_base_code_protocol_guid,
+ efi_image_handle, NULL );
+ err_no_base:
+ return rc;
+}
+
+/**
+ * Update command line
+ *
+ * @v shim Shim image
+ * @v cmdline Command line to update
+ * @ret rc Return status code
+ */
+static int efi_shim_cmdline ( struct image *shim, wchar_t **cmdline ) {
+ wchar_t *shimcmdline;
+ int len;
+ int rc;
+
+ /* Construct new command line */
+ len = ( shim->cmdline ?
+ efi_asprintf ( &shimcmdline, "%s %s", shim->name,
+ shim->cmdline ) :
+ efi_asprintf ( &shimcmdline, "%s %ls", shim->name,
+ *cmdline ) );
+ if ( len < 0 ) {
+ rc = len;
+ DBGC ( &efi_shim, "SHIM could not construct command line: "
+ "%s\n", strerror ( rc ) );
+ return rc;
+ }
+
+ /* Replace command line */
+ free ( *cmdline );
+ *cmdline = shimcmdline;
+
+ return 0;
+}
+
+/**
+ * Install UEFI shim special handling
+ *
+ * @v shim Shim image
+ * @v handle EFI device handle
+ * @v cmdline Command line to update
+ * @ret rc Return status code
+ */
+int efi_shim_install ( struct image *shim, EFI_HANDLE handle,
+ wchar_t **cmdline ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_RUNTIME_SERVICES *rs = efi_systab->RuntimeServices;
+ int rc;
+
+ /* Stop PXE base code */
+ if ( ( ! efi_shim_allow_pxe ) &&
+ ( ( rc = efi_shim_inhibit_pxe ( handle ) ) != 0 ) ) {
+ return rc;
+ }
+
+ /* Update command line */
+ if ( ( rc = efi_shim_cmdline ( shim, cmdline ) ) != 0 )
+ return rc;
+
+ /* Record original boot and runtime services functions */
+ efi_shim_orig_get_memory_map = bs->GetMemoryMap;
+ efi_shim_orig_exit_boot_services = bs->ExitBootServices;
+ efi_shim_orig_set_variable = rs->SetVariable;
+ efi_shim_orig_get_variable = rs->GetVariable;
+
+ /* Wrap relevant boot and runtime services functions */
+ bs->GetMemoryMap = efi_shim_get_memory_map;
+ bs->ExitBootServices = efi_shim_exit_boot_services;
+ rs->SetVariable = efi_shim_set_variable;
+ rs->GetVariable = efi_shim_get_variable;
+
+ return 0;
+}
+
+/**
+ * Uninstall UEFI shim special handling
+ *
+ */
+void efi_shim_uninstall ( void ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_RUNTIME_SERVICES *rs = efi_systab->RuntimeServices;
+
+ /* Restore original boot and runtime services functions */
+ bs->GetMemoryMap = efi_shim_orig_get_memory_map;
+ bs->ExitBootServices = efi_shim_orig_exit_boot_services;
+ rs->SetVariable = efi_shim_orig_set_variable;
+ rs->GetVariable = efi_shim_orig_get_variable;
+}
diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c
index c4f7d4ea..8443be99 100644
--- a/src/interface/efi/efi_snp.c
+++ b/src/interface/efi/efi_snp.c
@@ -1777,9 +1777,10 @@ static struct efi_snp_device * efi_snp_demux ( struct net_device *netdev ) {
* Create SNP device
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int efi_snp_probe ( struct net_device *netdev ) {
+static int efi_snp_probe ( struct net_device *netdev, void *priv __unused ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_device *efidev;
struct efi_snp_device *snpdev;
@@ -2017,8 +2018,9 @@ static int efi_snp_probe ( struct net_device *netdev ) {
* Handle SNP device or link state change
*
* @v netdev Network device
+ * @v priv Private data
*/
-static void efi_snp_notify ( struct net_device *netdev ) {
+static void efi_snp_notify ( struct net_device *netdev, void *priv __unused ) {
struct efi_snp_device *snpdev;
/* Locate SNP device */
@@ -2042,8 +2044,9 @@ static void efi_snp_notify ( struct net_device *netdev ) {
* Destroy SNP device
*
* @v netdev Network device
+ * @v priv Private data
*/
-static void efi_snp_remove ( struct net_device *netdev ) {
+static void efi_snp_remove ( struct net_device *netdev, void *priv __unused ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_snp_device *snpdev;
int leak = efi_shutdown_in_progress;
diff --git a/src/interface/efi/efi_strings.c b/src/interface/efi/efi_strings.c
index aa3afc64..765b23ca 100644
--- a/src/interface/efi/efi_strings.c
+++ b/src/interface/efi/efi_strings.c
@@ -25,6 +25,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stddef.h>
#include <stdarg.h>
+#include <stdlib.h>
+#include <errno.h>
#include <ipxe/vsprintf.h>
#include <ipxe/efi/efi_strings.h>
@@ -150,3 +152,45 @@ int efi_ssnprintf ( wchar_t *wbuf, ssize_t swsize, const char *fmt, ... ) {
va_end ( args );
return len;
}
+
+/**
+ * Write a formatted string to newly allocated memory
+ *
+ * @v wstrp Pointer to hold allocated string
+ * @v fmt Format string
+ * @v args Arguments corresponding to the format string
+ * @ret len Length of formatted string (in wide characters)
+ */
+int efi_vasprintf ( wchar_t **wstrp, const char *fmt, va_list args ) {
+ size_t len;
+ va_list args_tmp;
+
+ /* Calculate length needed for string */
+ va_copy ( args_tmp, args );
+ len = ( efi_vsnprintf ( NULL, 0, fmt, args_tmp ) + 1 );
+ va_end ( args_tmp );
+
+ /* Allocate and fill string */
+ *wstrp = malloc ( len * sizeof ( **wstrp ) );
+ if ( ! *wstrp )
+ return -ENOMEM;
+ return efi_vsnprintf ( *wstrp, len, fmt, args );
+}
+
+/**
+ * Write a formatted string to newly allocated memory
+ *
+ * @v wstrp Pointer to hold allocated string
+ * @v fmt Format string
+ * @v ... Arguments corresponding to the format string
+ * @ret len Length of formatted string (in wide characters)
+ */
+int efi_asprintf ( wchar_t **wstrp, const char *fmt, ... ) {
+ va_list args;
+ int len;
+
+ va_start ( args, fmt );
+ len = efi_vasprintf ( wstrp, fmt, args );
+ va_end ( args );
+ return len;
+}
diff --git a/src/interface/efi/efi_veto.c b/src/interface/efi/efi_veto.c
index b616539d..a3b60d65 100644
--- a/src/interface/efi/efi_veto.c
+++ b/src/interface/efi/efi_veto.c
@@ -37,8 +37,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*
*/
-/** A driver veto */
-struct efi_veto {
+/** A driver veto candidate */
+struct efi_veto_candidate {
/** Veto name (for debugging) */
const char *name;
/**
@@ -57,22 +57,38 @@ struct efi_veto {
const char *manufacturer, const CHAR16 *name );
};
+/** A driver veto */
+struct efi_veto {
+ /** Driver binding handle */
+ EFI_HANDLE driver;
+ /** Driving binding protocol */
+ EFI_DRIVER_BINDING_PROTOCOL *binding;
+ /** Image handle */
+ EFI_HANDLE image;
+ /** Loaded image protocol */
+ EFI_LOADED_IMAGE_PROTOCOL *loaded;
+};
+
/**
* Unload an EFI driver
*
- * @v driver Driver binding handle
+ * @v veto Driver veto
* @ret rc Return status code
*/
-static int efi_veto_unload ( EFI_HANDLE driver ) {
+static int efi_veto_unload ( struct efi_veto *veto ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_HANDLE driver = veto->driver;
+ EFI_HANDLE image = veto->image;
EFI_STATUS efirc;
int rc;
/* Unload the driver */
- if ( ( efirc = bs->UnloadImage ( driver ) ) != 0 ) {
+ if ( ( efirc = bs->UnloadImage ( image ) ) != 0 ) {
rc = -EEFI ( efirc );
- DBGC ( driver, "EFIVETO %s could not unload: %s\n",
- efi_handle_name ( driver ), strerror ( rc ) );
+ DBGC ( driver, "EFIVETO %s could not unload",
+ efi_handle_name ( driver ) );
+ DBGC ( driver, " %s: %s\n", efi_handle_name ( image ),
+ strerror ( rc ) );
return rc;
}
@@ -82,11 +98,12 @@ static int efi_veto_unload ( EFI_HANDLE driver ) {
/**
* Disconnect an EFI driver from all handles
*
- * @v driver Driver binding handle
+ * @v veto Driver veto
* @ret rc Return status code
*/
-static int efi_veto_disconnect ( EFI_HANDLE driver ) {
+static int efi_veto_disconnect ( struct efi_veto *veto ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_HANDLE driver = veto->driver;
EFI_HANDLE *handles;
EFI_HANDLE handle;
UINTN count;
@@ -131,11 +148,12 @@ static int efi_veto_disconnect ( EFI_HANDLE driver ) {
/**
* Uninstall an EFI driver binding protocol
*
- * @v driver Driver binding handle
+ * @v veto Driver veto
* @ret rc Return status code
*/
-static int efi_veto_uninstall ( EFI_HANDLE driver ) {
+static int efi_veto_uninstall ( struct efi_veto *veto ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_HANDLE driver = veto->driver;
union {
EFI_DRIVER_BINDING_PROTOCOL *binding;
void *interface;
@@ -178,14 +196,16 @@ static int efi_veto_uninstall ( EFI_HANDLE driver ) {
/**
* Close protocol on handle potentially opened by an EFI driver
*
- * @v driver Driver binding handle
+ * @v veto Driver veto
* @v handle Potentially opened handle
* @v protocol Opened protocol
* @ret rc Return status code
*/
-static int efi_veto_close_protocol ( EFI_HANDLE driver, EFI_HANDLE handle,
+static int efi_veto_close_protocol ( struct efi_veto *veto, EFI_HANDLE handle,
EFI_GUID *protocol ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_HANDLE driver = veto->driver;
+ EFI_HANDLE image = veto->image;
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *openers;
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *opener;
EFI_HANDLE controller;
@@ -207,9 +227,11 @@ static int efi_veto_close_protocol ( EFI_HANDLE driver, EFI_HANDLE handle,
/* Close anything opened by this driver */
for ( i = 0 ; i < count ; i++ ) {
- opener = &openers[i];
- if ( opener->AgentHandle != driver )
+ opener = &openers[ count - i - 1 ];
+ if ( ( opener->AgentHandle != driver ) &&
+ ( opener->AgentHandle != image ) ) {
continue;
+ }
controller = opener->ControllerHandle;
DBGC_EFI_OPENER ( driver, handle, protocol, opener );
if ( ( efirc = bs->CloseProtocol ( handle, protocol, driver,
@@ -235,13 +257,15 @@ static int efi_veto_close_protocol ( EFI_HANDLE driver, EFI_HANDLE handle,
/**
* Close handle potentially opened by an EFI driver
*
- * @v driver Driver binding handle
+ * @v veto Driver veto
* @v handle Potentially opened handle
* @ret rc Return status code
*/
-static int efi_veto_close_handle ( EFI_HANDLE driver, EFI_HANDLE handle ) {
+static int efi_veto_close_handle ( struct efi_veto *veto, EFI_HANDLE handle ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_HANDLE driver = veto->driver;
EFI_GUID **protocols;
+ EFI_GUID *protocol;
UINTN count;
unsigned int i;
EFI_STATUS efirc;
@@ -260,8 +284,9 @@ static int efi_veto_close_handle ( EFI_HANDLE driver, EFI_HANDLE handle ) {
/* Close each protocol */
for ( i = 0 ; i < count ; i++ ) {
- if ( ( rc = efi_veto_close_protocol ( driver, handle,
- protocols[i] ) ) != 0 )
+ protocol = protocols[ count - i - 1];
+ if ( ( rc = efi_veto_close_protocol ( veto, handle,
+ protocol ) ) != 0 )
goto err_close;
}
@@ -277,12 +302,14 @@ static int efi_veto_close_handle ( EFI_HANDLE driver, EFI_HANDLE handle ) {
/**
* Close all remaining handles opened by an EFI driver
*
- * @v driver Driver binding handle
+ * @v veto Driver veto
* @ret rc Return status code
*/
-static int efi_veto_close ( EFI_HANDLE driver ) {
+static int efi_veto_close ( struct efi_veto *veto ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_HANDLE driver = veto->driver;
EFI_HANDLE *handles;
+ EFI_HANDLE handle;
UINTN count;
unsigned int i;
EFI_STATUS efirc;
@@ -299,8 +326,8 @@ static int efi_veto_close ( EFI_HANDLE driver ) {
/* Close each handle */
for ( i = 0 ; i < count ; i++ ) {
- if ( ( rc = efi_veto_close_handle ( driver,
- handles[i] ) ) != 0 )
+ handle = handles[ count - i - 1 ];
+ if ( ( rc = efi_veto_close_handle ( veto, handle ) ) != 0 )
goto err_close;
}
@@ -318,22 +345,23 @@ static int efi_veto_close ( EFI_HANDLE driver ) {
/**
* Terminate an EFI driver with extreme prejudice
*
- * @v driver Driver binding handle
+ * @v veto Driver veto
* @ret rc Return status code
*/
-static int efi_veto_destroy ( EFI_HANDLE driver ) {
+static int efi_veto_destroy ( struct efi_veto *veto ) {
+ EFI_HANDLE driver = veto->driver;
int rc;
/* Disconnect driver from all handles */
- if ( ( rc = efi_veto_disconnect ( driver ) ) != 0 )
+ if ( ( rc = efi_veto_disconnect ( veto ) ) != 0 )
return rc;
/* Uninstall driver binding protocol */
- if ( ( rc = efi_veto_uninstall ( driver ) ) != 0 )
+ if ( ( rc = efi_veto_uninstall ( veto ) ) != 0 )
return rc;
/* Close any remaining opened handles */
- if ( ( rc = efi_veto_close ( driver ) ) != 0 )
+ if ( ( rc = efi_veto_close ( veto ) ) != 0 )
return rc;
DBGC ( driver, "EFIVETO %s forcibly removed\n",
@@ -344,18 +372,18 @@ static int efi_veto_destroy ( EFI_HANDLE driver ) {
/**
* Veto an EFI driver
*
- * @v driver Driver binding handle
+ * @v veto Driver veto
* @ret rc Return status code
*/
-static int efi_veto_driver ( EFI_HANDLE driver ) {
+static int efi_veto_driver ( struct efi_veto *veto ) {
int rc;
/* Try gracefully unloading the driver */
- if ( ( rc = efi_veto_unload ( driver ) ) == 0 )
+ if ( ( rc = efi_veto_unload ( veto ) ) == 0 )
return 0;
/* If that fails, use a hammer */
- if ( ( rc = efi_veto_destroy ( driver ) ) == 0 )
+ if ( ( rc = efi_veto_destroy ( veto ) ) == 0 )
return 0;
return rc;
@@ -435,8 +463,39 @@ efi_veto_hp_xhci ( EFI_DRIVER_BINDING_PROTOCOL *binding __unused,
return 0;
}
+/**
+ * Veto VMware UefiPxeBcDxe driver
+ *
+ * @v binding Driver binding protocol
+ * @v loaded Loaded image protocol
+ * @v wtf Component name protocol, if present
+ * @v manufacturer Manufacturer name, if present
+ * @v name Driver name, if present
+ * @ret vetoed Driver is to be vetoed
+ */
+static int
+efi_veto_vmware_uefipxebc ( EFI_DRIVER_BINDING_PROTOCOL *binding __unused,
+ EFI_LOADED_IMAGE_PROTOCOL *loaded __unused,
+ EFI_COMPONENT_NAME_PROTOCOL *wtf __unused,
+ const char *manufacturer, const CHAR16 *name ) {
+ static const CHAR16 uefipxebc[] = L"UEFI PXE Base Code Driver";
+ static const char *vmware = "VMware, Inc.";
+
+ /* Check manufacturer and driver name */
+ if ( ! manufacturer )
+ return 0;
+ if ( ! name )
+ return 0;
+ if ( strcmp ( manufacturer, vmware ) != 0 )
+ return 0;
+ if ( memcmp ( name, uefipxebc, sizeof ( uefipxebc ) ) != 0 )
+ return 0;
+
+ return 1;
+}
+
/** Driver vetoes */
-static struct efi_veto efi_vetoes[] = {
+static struct efi_veto_candidate efi_vetoes[] = {
{
.name = "Ip4Config",
.veto = efi_veto_ip4config,
@@ -445,6 +504,10 @@ static struct efi_veto efi_vetoes[] = {
.name = "HP Xhci",
.veto = efi_veto_hp_xhci,
},
+ {
+ .name = "VMware UefiPxeBc",
+ .veto = efi_veto_vmware_uefipxebc,
+ },
};
/**
@@ -452,11 +515,11 @@ static struct efi_veto efi_vetoes[] = {
*
* @v driver Driver binding handle
* @v manufacturer Manufacturer name, if present
- * @ret veto Driver veto, or NULL
+ * @ret veto Driver veto to fill in
* @ret rc Return status code
*/
static int efi_veto_find ( EFI_HANDLE driver, const char *manufacturer,
- struct efi_veto **veto ) {
+ struct efi_veto *veto ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
union {
EFI_DRIVER_BINDING_PROTOCOL *binding;
@@ -480,7 +543,7 @@ static int efi_veto_find ( EFI_HANDLE driver, const char *manufacturer,
efi_handle_name ( driver ) );
/* Mark as not vetoed */
- *veto = NULL;
+ memset ( veto, 0, sizeof ( *veto ) );
/* Open driver binding protocol */
if ( ( efirc = bs->OpenProtocol (
@@ -532,7 +595,13 @@ static int efi_veto_find ( EFI_HANDLE driver, const char *manufacturer,
sizeof ( efi_vetoes[0] ) ) ; i++ ) {
if ( efi_vetoes[i].veto ( binding.binding, loaded.loaded,
wtf.wtf, manufacturer, name ) ) {
- *veto = &efi_vetoes[i];
+ DBGC ( driver, "EFIVETO %s is vetoed (%s)\n",
+ efi_handle_name ( driver ),
+ efi_vetoes[i].name );
+ veto->driver = driver;
+ veto->binding = binding.binding;
+ veto->image = image;
+ veto->loaded = loaded.loaded;
break;
}
}
@@ -560,10 +629,10 @@ static int efi_veto_find ( EFI_HANDLE driver, const char *manufacturer,
*/
void efi_veto ( void ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
- struct efi_veto *veto;
+ struct efi_veto veto;
EFI_HANDLE *drivers;
EFI_HANDLE driver;
- UINTN num_drivers;
+ UINTN count;
unsigned int i;
char *manufacturer;
EFI_STATUS efirc;
@@ -572,7 +641,7 @@ void efi_veto ( void ) {
/* Locate all driver binding protocol handles */
if ( ( efirc = bs->LocateHandleBuffer (
ByProtocol, &efi_driver_binding_protocol_guid,
- NULL, &num_drivers, &drivers ) ) != 0 ) {
+ NULL, &count, &drivers ) ) != 0 ) {
rc = -EEFI ( efirc );
DBGC ( &efi_vetoes, "EFIVETO could not list all drivers: "
"%s\n", strerror ( rc ) );
@@ -582,10 +651,11 @@ void efi_veto ( void ) {
/* Get manufacturer name */
fetch_string_setting_copy ( NULL, &manufacturer_setting,
&manufacturer );
+ DBGC ( &efi_vetoes, "EFIVETO manufacturer is \"%s\"\n", manufacturer );
/* Unload any vetoed drivers */
- for ( i = 0 ; i < num_drivers ; i++ ) {
- driver = drivers[i];
+ for ( i = 0 ; i < count ; i++ ) {
+ driver = drivers[ count - i - 1 ];
if ( ( rc = efi_veto_find ( driver, manufacturer,
&veto ) ) != 0 ) {
DBGC ( driver, "EFIVETO %s could not determine "
@@ -593,11 +663,9 @@ void efi_veto ( void ) {
efi_handle_name ( driver ), strerror ( rc ) );
continue;
}
- if ( ! veto )
+ if ( ! veto.driver )
continue;
- DBGC ( driver, "EFIVETO %s is vetoed (%s)\n",
- efi_handle_name ( driver ), veto->name );
- if ( ( rc = efi_veto_driver ( driver ) ) != 0 ) {
+ if ( ( rc = efi_veto_driver ( &veto ) ) != 0 ) {
DBGC ( driver, "EFIVETO %s could not veto: %s\n",
efi_handle_name ( driver ), strerror ( rc ) );
}
diff --git a/src/net/80211/wpa.c b/src/net/80211/wpa.c
index 1484d0e8..17c11b8e 100644
--- a/src/net/80211/wpa.c
+++ b/src/net/80211/wpa.c
@@ -761,13 +761,14 @@ static int wpa_handle_1_of_2 ( struct wpa_common_ctx *ctx,
/**
* Handle receipt of EAPOL-Key frame for WPA
*
- * @v iob I/O buffer
- * @v netdev Network device
- * @v ll_source Source link-layer address
+ * @v supplicant EAPoL supplicant
+ * @v iob I/O buffer
+ * @v ll_source Source link-layer address
*/
-static int eapol_key_rx ( struct io_buffer *iob, struct net_device *netdev,
- const void *ll_source )
+static int eapol_key_rx ( struct eapol_supplicant *supplicant,
+ struct io_buffer *iob, const void *ll_source )
{
+ struct net_device *netdev = supplicant->eap.netdev;
struct net80211_device *dev = net80211_get ( netdev );
struct eapol_header *eapol;
struct eapol_key_pkt *pkt;
diff --git a/src/net/eap.c b/src/net/eap.c
index 8d1d540f..beaeb61d 100644
--- a/src/net/eap.c
+++ b/src/net/eap.c
@@ -36,10 +36,11 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/**
* Handle EAP Request-Identity
*
- * @v netdev Network device
+ * @v supplicant EAP supplicant
* @ret rc Return status code
*/
-static int eap_rx_request_identity ( struct net_device *netdev ) {
+static int eap_rx_request_identity ( struct eap_supplicant *supplicant ) {
+ struct net_device *netdev = supplicant->netdev;
/* Treat Request-Identity as blocking the link */
DBGC ( netdev, "EAP %s Request-Identity blocking link\n",
@@ -52,13 +53,14 @@ static int eap_rx_request_identity ( struct net_device *netdev ) {
/**
* Handle EAP Request
*
- * @v netdev Network device
+ * @v supplicant EAP supplicant
* @v req EAP request
* @v len Length of EAP request
* @ret rc Return status code
*/
-static int eap_rx_request ( struct net_device *netdev,
+static int eap_rx_request ( struct eap_supplicant *supplicant,
const struct eap_request *req, size_t len ) {
+ struct net_device *netdev = supplicant->netdev;
/* Sanity check */
if ( len < sizeof ( *req ) ) {
@@ -67,10 +69,13 @@ static int eap_rx_request ( struct net_device *netdev,
return -EINVAL;
}
+ /* Mark authentication as incomplete */
+ supplicant->done = 0;
+
/* Handle according to type */
switch ( req->type ) {
case EAP_TYPE_IDENTITY:
- return eap_rx_request_identity ( netdev );
+ return eap_rx_request_identity ( supplicant );
default:
DBGC ( netdev, "EAP %s requested type %d unknown:\n",
netdev->name, req->type );
@@ -82,10 +87,14 @@ static int eap_rx_request ( struct net_device *netdev,
/**
* Handle EAP Success
*
- * @v netdev Network device
+ * @v supplicant EAP supplicant
* @ret rc Return status code
*/
-static int eap_rx_success ( struct net_device *netdev ) {
+static int eap_rx_success ( struct eap_supplicant *supplicant ) {
+ struct net_device *netdev = supplicant->netdev;
+
+ /* Mark authentication as complete */
+ supplicant->done = 1;
/* Mark link as unblocked */
DBGC ( netdev, "EAP %s Success\n", netdev->name );
@@ -97,10 +106,14 @@ static int eap_rx_success ( struct net_device *netdev ) {
/**
* Handle EAP Failure
*
- * @v netdev Network device
+ * @v supplicant EAP supplicant
* @ret rc Return status code
*/
-static int eap_rx_failure ( struct net_device *netdev ) {
+static int eap_rx_failure ( struct eap_supplicant *supplicant ) {
+ struct net_device *netdev = supplicant->netdev;
+
+ /* Mark authentication as complete */
+ supplicant->done = 1;
/* Record error */
DBGC ( netdev, "EAP %s Failure\n", netdev->name );
@@ -110,12 +123,14 @@ static int eap_rx_failure ( struct net_device *netdev ) {
/**
* Handle EAP packet
*
- * @v netdev Network device
+ * @v supplicant EAP supplicant
* @v data EAP packet
* @v len Length of EAP packet
* @ret rc Return status code
*/
-int eap_rx ( struct net_device *netdev, const void *data, size_t len ) {
+int eap_rx ( struct eap_supplicant *supplicant, const void *data,
+ size_t len ) {
+ struct net_device *netdev = supplicant->netdev;
const union eap_packet *eap = data;
/* Sanity check */
@@ -128,11 +143,11 @@ int eap_rx ( struct net_device *netdev, const void *data, size_t len ) {
/* Handle according to code */
switch ( eap->hdr.code ) {
case EAP_CODE_REQUEST:
- return eap_rx_request ( netdev, &eap->req, len );
+ return eap_rx_request ( supplicant, &eap->req, len );
case EAP_CODE_SUCCESS:
- return eap_rx_success ( netdev );
+ return eap_rx_success ( supplicant );
case EAP_CODE_FAILURE:
- return eap_rx_failure ( netdev );
+ return eap_rx_failure ( supplicant );
default:
DBGC ( netdev, "EAP %s unsupported code %d\n",
netdev->name, eap->hdr.code );
diff --git a/src/net/eapol.c b/src/net/eapol.c
index 3578f0e3..1b843e89 100644
--- a/src/net/eapol.c
+++ b/src/net/eapol.c
@@ -28,7 +28,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <byteswap.h>
#include <ipxe/iobuf.h>
#include <ipxe/if_ether.h>
+#include <ipxe/if_arp.h>
#include <ipxe/netdevice.h>
+#include <ipxe/vlan.h>
+#include <ipxe/retry.h>
#include <ipxe/eap.h>
#include <ipxe/eapol.h>
@@ -38,6 +41,44 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*
*/
+struct net_driver eapol_driver __net_driver;
+
+/** EAPoL destination MAC address */
+static const uint8_t eapol_mac[ETH_ALEN] = {
+ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03
+};
+
+/**
+ * Update EAPoL supplicant state
+ *
+ * @v supplicant EAPoL supplicant
+ * @v timeout Timer ticks until next EAPoL-Start (if applicable)
+ */
+static void eapol_update ( struct eapol_supplicant *supplicant,
+ unsigned long timeout ) {
+ struct net_device *netdev = supplicant->eap.netdev;
+
+ /* Check device and EAP state */
+ if ( netdev_is_open ( netdev ) && netdev_link_ok ( netdev ) ) {
+ if ( supplicant->eap.done ) {
+
+ /* EAP has completed: stop sending EAPoL-Start */
+ stop_timer ( &supplicant->timer );
+
+ } else if ( ! timer_running ( &supplicant->timer ) ) {
+
+ /* EAP has not yet begun: start sending EAPoL-Start */
+ start_timer_fixed ( &supplicant->timer, timeout );
+ }
+
+ } else {
+
+ /* Not ready: clear completion and stop sending EAPoL-Start */
+ supplicant->eap.done = 0;
+ stop_timer ( &supplicant->timer );
+ }
+}
+
/**
* Process EAPoL packet
*
@@ -51,12 +92,25 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
static int eapol_rx ( struct io_buffer *iobuf, struct net_device *netdev,
const void *ll_dest __unused, const void *ll_source,
unsigned int flags __unused ) {
+ struct eapol_supplicant *supplicant;
struct eapol_header *eapol;
struct eapol_handler *handler;
size_t remaining;
size_t len;
int rc;
+ /* Find matching supplicant */
+ supplicant = netdev_priv ( netdev, &eapol_driver );
+
+ /* Ignore non-EAPoL devices */
+ if ( ! supplicant->eap.netdev ) {
+ DBGC ( netdev, "EAPOL %s is not an EAPoL device\n",
+ netdev->name );
+ DBGC_HDA ( netdev, 0, iobuf->data, iob_len ( iobuf ) );
+ rc = -ENOTTY;
+ goto drop;
+ }
+
/* Sanity checks */
if ( iob_len ( iobuf ) < sizeof ( *eapol ) ) {
DBGC ( netdev, "EAPOL %s underlength header:\n",
@@ -83,7 +137,7 @@ static int eapol_rx ( struct io_buffer *iobuf, struct net_device *netdev,
/* Handle according to type */
for_each_table_entry ( handler, EAPOL_HANDLERS ) {
if ( handler->type == eapol->type ) {
- return handler->rx ( iob_disown ( iobuf ) , netdev,
+ return handler->rx ( supplicant, iob_disown ( iobuf ),
ll_source );
}
}
@@ -107,12 +161,14 @@ struct net_protocol eapol_protocol __net_protocol = {
/**
* Process EAPoL-encapsulated EAP packet
*
- * @v netdev Network device
+ * @v supplicant EAPoL supplicant
* @v ll_source Link-layer source address
* @ret rc Return status code
*/
-static int eapol_eap_rx ( struct io_buffer *iobuf, struct net_device *netdev,
+static int eapol_eap_rx ( struct eapol_supplicant *supplicant,
+ struct io_buffer *iobuf,
const void *ll_source __unused ) {
+ struct net_device *netdev = supplicant->eap.netdev;
struct eapol_header *eapol;
int rc;
@@ -123,12 +179,16 @@ static int eapol_eap_rx ( struct io_buffer *iobuf, struct net_device *netdev,
eapol = iob_pull ( iobuf, sizeof ( *eapol ) );
/* Process EAP packet */
- if ( ( rc = eap_rx ( netdev, iobuf->data, iob_len ( iobuf ) ) ) != 0 ) {
+ if ( ( rc = eap_rx ( &supplicant->eap, iobuf->data,
+ iob_len ( iobuf ) ) ) != 0 ) {
DBGC ( netdev, "EAPOL %s v%d EAP failed: %s\n",
netdev->name, eapol->version, strerror ( rc ) );
goto drop;
}
+ /* Update supplicant state */
+ eapol_update ( supplicant, EAPOL_START_INTERVAL );
+
drop:
free_iob ( iobuf );
return rc;
@@ -139,3 +199,131 @@ struct eapol_handler eapol_eap __eapol_handler = {
.type = EAPOL_TYPE_EAP,
.rx = eapol_eap_rx,
};
+
+/**
+ * Transmit EAPoL packet
+ *
+ * @v supplicant EAPoL supplicant
+ * @v type Packet type
+ * @v data Packet body
+ * @v len Length of packet body
+ * @ret rc Return status code
+ */
+static int eapol_tx ( struct eapol_supplicant *supplicant, unsigned int type,
+ const void *data, size_t len ) {
+ struct net_device *netdev = supplicant->eap.netdev;
+ struct io_buffer *iobuf;
+ struct eapol_header *eapol;
+ int rc;
+
+ /* Allocate I/O buffer */
+ iobuf = alloc_iob ( MAX_LL_HEADER_LEN + sizeof ( *eapol ) + len );
+ if ( ! iobuf )
+ return -ENOMEM;
+ iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
+
+ /* Construct EAPoL header */
+ eapol = iob_put ( iobuf, sizeof ( *eapol ) );
+ eapol->version = EAPOL_VERSION_2001;
+ eapol->type = type;
+ eapol->len = htons ( len );
+
+ /* Append packet body */
+ memcpy ( iob_put ( iobuf, len ), data, len );
+
+ /* Transmit packet */
+ if ( ( rc = net_tx ( iob_disown ( iobuf ), netdev, &eapol_protocol,
+ &eapol_mac, netdev->ll_addr ) ) != 0 ) {
+ DBGC ( netdev, "EAPOL %s could not transmit type %d: %s\n",
+ netdev->name, type, strerror ( rc ) );
+ DBGC_HDA ( netdev, 0, data, len );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Transmit EAPoL-encapsulated EAP packet
+ *
+ * @v supplicant EAPoL supplicant
+ * @v ll_source Link-layer source address
+ * @ret rc Return status code
+ */
+static int eapol_eap_tx ( struct eap_supplicant *eap, const void *data,
+ size_t len ) {
+ struct eapol_supplicant *supplicant =
+ container_of ( eap, struct eapol_supplicant, eap );
+
+ /* Transmit encapsulated packet */
+ return eapol_tx ( supplicant, EAPOL_TYPE_EAP, data, len );
+}
+
+/**
+ * (Re)transmit EAPoL-Start packet
+ *
+ * @v timer EAPoL-Start timer
+ * @v expired Failure indicator
+ */
+static void eapol_expired ( struct retry_timer *timer, int fail __unused ) {
+ struct eapol_supplicant *supplicant =
+ container_of ( timer, struct eapol_supplicant, timer );
+ struct net_device *netdev = supplicant->eap.netdev;
+
+ /* Schedule next transmission */
+ start_timer_fixed ( timer, EAPOL_START_INTERVAL );
+
+ /* Transmit EAPoL-Start, ignoring errors */
+ DBGC2 ( netdev, "EAPOL %s transmitting Start\n", netdev->name );
+ eapol_tx ( supplicant, EAPOL_TYPE_START, NULL, 0 );
+}
+
+/**
+ * Create EAPoL supplicant
+ *
+ * @v netdev Network device
+ * @v priv Private data
+ * @ret rc Return status code
+ */
+static int eapol_probe ( struct net_device *netdev, void *priv ) {
+ struct eapol_supplicant *supplicant = priv;
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
+
+ /* Ignore non-EAPoL devices */
+ if ( ll_protocol->ll_proto != htons ( ARPHRD_ETHER ) )
+ return 0;
+ if ( vlan_tag ( netdev ) )
+ return 0;
+
+ /* Initialise structure */
+ supplicant->eap.netdev = netdev;
+ supplicant->eap.tx = eapol_eap_tx;
+ timer_init ( &supplicant->timer, eapol_expired, &netdev->refcnt );
+
+ return 0;
+}
+
+/**
+ * Handle EAPoL supplicant state change
+ *
+ * @v netdev Network device
+ * @v priv Private data
+ */
+static void eapol_notify ( struct net_device *netdev __unused, void *priv ) {
+ struct eapol_supplicant *supplicant = priv;
+
+ /* Ignore non-EAPoL devices */
+ if ( ! supplicant->eap.netdev )
+ return;
+
+ /* Update supplicant state */
+ eapol_update ( supplicant, 0 );
+}
+
+/** EAPoL driver */
+struct net_driver eapol_driver __net_driver = {
+ .name = "EAPoL",
+ .priv_len = sizeof ( struct eapol_supplicant ),
+ .probe = eapol_probe,
+ .notify = eapol_notify,
+};
diff --git a/src/net/fcoe.c b/src/net/fcoe.c
index f910eeea..9f3ddf88 100644
--- a/src/net/fcoe.c
+++ b/src/net/fcoe.c
@@ -69,10 +69,6 @@ FEATURE ( FEATURE_PROTOCOL, "FCoE", DHCP_EB_FEATURE_FCOE, 1 );
/** An FCoE port */
struct fcoe_port {
- /** Reference count */
- struct refcnt refcnt;
- /** List of FCoE ports */
- struct list_head list;
/** Transport interface */
struct interface transport;
/** Network device */
@@ -115,6 +111,7 @@ enum fcoe_flags {
FCOE_VLAN_TIMED_OUT = 0x0020,
};
+struct net_driver fcoe_driver __net_driver;
struct net_protocol fcoe_protocol __net_protocol;
struct net_protocol fip_protocol __net_protocol;
@@ -152,9 +149,6 @@ static uint8_t default_fcf_mac[ETH_ALEN] =
/** Maximum number of missing discovery advertisements */
#define FCOE_MAX_FIP_MISSING_KEEPALIVES 4
-/** List of FCoE ports */
-static LIST_HEAD ( fcoe_ports );
-
/******************************************************************************
*
* FCoE protocol
@@ -163,22 +157,6 @@ static LIST_HEAD ( fcoe_ports );
*/
/**
- * Identify FCoE port by network device
- *
- * @v netdev Network device
- * @ret fcoe FCoE port, or NULL
- */
-static struct fcoe_port * fcoe_demux ( struct net_device *netdev ) {
- struct fcoe_port *fcoe;
-
- list_for_each_entry ( fcoe, &fcoe_ports, list ) {
- if ( fcoe->netdev == netdev )
- return fcoe;
- }
- return NULL;
-}
-
-/**
* Reset FCoE port
*
* @v fcoe FCoE port
@@ -348,7 +326,8 @@ static int fcoe_rx ( struct io_buffer *iobuf, struct net_device *netdev,
int rc;
/* Identify FCoE port */
- if ( ( fcoe = fcoe_demux ( netdev ) ) == NULL ) {
+ fcoe = netdev_priv ( netdev, &fcoe_driver );
+ if ( ! fcoe->netdev ) {
DBG ( "FCoE received frame for net device %s missing FCoE "
"port\n", netdev->name );
rc = -ENOTCONN;
@@ -448,9 +427,6 @@ static void fcoe_close ( struct fcoe_port *fcoe, int rc ) {
stop_timer ( &fcoe->timer );
intf_shutdown ( &fcoe->transport, rc );
- netdev_put ( fcoe->netdev );
- list_del ( &fcoe->list );
- ref_put ( &fcoe->refcnt );
}
/**
@@ -947,7 +923,8 @@ static int fcoe_fip_rx ( struct io_buffer *iobuf,
int rc;
/* Identify FCoE port */
- if ( ( fcoe = fcoe_demux ( netdev ) ) == NULL ) {
+ fcoe = netdev_priv ( netdev, &fcoe_driver );
+ if ( ! fcoe->netdev ) {
DBG ( "FCoE received FIP frame for net device %s missing FCoE "
"port\n", netdev->name );
rc = -ENOTCONN;
@@ -1110,31 +1087,24 @@ static void fcoe_expired ( struct retry_timer *timer, int over __unused ) {
* Create FCoE port
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int fcoe_probe ( struct net_device *netdev ) {
+static int fcoe_probe ( struct net_device *netdev, void *priv ) {
struct ll_protocol *ll_protocol = netdev->ll_protocol;
- struct fcoe_port *fcoe;
- int rc;
+ struct fcoe_port *fcoe = priv;
/* Sanity check */
if ( ll_protocol->ll_proto != htons ( ARPHRD_ETHER ) ) {
/* Not an error; simply skip this net device */
DBG ( "FCoE skipping non-Ethernet device %s\n", netdev->name );
- rc = 0;
- goto err_non_ethernet;
+ return 0;
}
- /* Allocate and initialise structure */
- fcoe = zalloc ( sizeof ( *fcoe ) );
- if ( ! fcoe ) {
- rc = -ENOMEM;
- goto err_zalloc;
- }
- ref_init ( &fcoe->refcnt, NULL );
- intf_init ( &fcoe->transport, &fcoe_transport_desc, &fcoe->refcnt );
- timer_init ( &fcoe->timer, fcoe_expired, &fcoe->refcnt );
- fcoe->netdev = netdev_get ( netdev );
+ /* Initialise structure */
+ intf_init ( &fcoe->transport, &fcoe_transport_desc, &netdev->refcnt );
+ timer_init ( &fcoe->timer, fcoe_expired, &netdev->refcnt );
+ fcoe->netdev = netdev;
/* Construct node and port names */
fcoe->node_wwn.fcoe.authority = htons ( FCOE_AUTHORITY_IEEE );
@@ -1148,30 +1118,21 @@ static int fcoe_probe ( struct net_device *netdev ) {
fc_ntoa ( &fcoe->node_wwn.fc ) );
DBGC ( fcoe, " port %s\n", fc_ntoa ( &fcoe->port_wwn.fc ) );
- /* Transfer reference to port list */
- list_add ( &fcoe->list, &fcoe_ports );
return 0;
-
- netdev_put ( fcoe->netdev );
- err_zalloc:
- err_non_ethernet:
- return rc;
}
/**
* Handle FCoE port device or link state change
*
* @v netdev Network device
+ * @v priv Private data
*/
-static void fcoe_notify ( struct net_device *netdev ) {
- struct fcoe_port *fcoe;
+static void fcoe_notify ( struct net_device *netdev, void *priv ) {
+ struct fcoe_port *fcoe = priv;
- /* Sanity check */
- if ( ( fcoe = fcoe_demux ( netdev ) ) == NULL ) {
- DBG ( "FCoE notification for net device %s missing FCoE "
- "port\n", netdev->name );
+ /* Skip non-FCoE net devices */
+ if ( ! fcoe->netdev )
return;
- }
/* Reset the FCoE link if necessary */
if ( ! ( netdev_is_open ( netdev ) &&
@@ -1185,16 +1146,14 @@ static void fcoe_notify ( struct net_device *netdev ) {
* Destroy FCoE port
*
* @v netdev Network device
+ * @v priv Private data
*/
-static void fcoe_remove ( struct net_device *netdev ) {
- struct fcoe_port *fcoe;
+static void fcoe_remove ( struct net_device *netdev __unused, void *priv ) {
+ struct fcoe_port *fcoe = priv;
- /* Sanity check */
- if ( ( fcoe = fcoe_demux ( netdev ) ) == NULL ) {
- DBG ( "FCoE removal of net device %s missing FCoE port\n",
- netdev->name );
+ /* Skip non-FCoE net devices */
+ if ( ! fcoe->netdev )
return;
- }
/* Close FCoE device */
fcoe_close ( fcoe, 0 );
@@ -1203,6 +1162,7 @@ static void fcoe_remove ( struct net_device *netdev ) {
/** FCoE driver */
struct net_driver fcoe_driver __net_driver = {
.name = "FCoE",
+ .priv_len = sizeof ( struct fcoe_port ),
.probe = fcoe_probe,
.notify = fcoe_notify,
.remove = fcoe_remove,
diff --git a/src/net/infiniband/xsigo.c b/src/net/infiniband/xsigo.c
index 4f5c618d..5e805fa0 100644
--- a/src/net/infiniband/xsigo.c
+++ b/src/net/infiniband/xsigo.c
@@ -1829,8 +1829,10 @@ struct ib_driver xsigo_ib_driver __ib_driver = {
* Handle device or link status change
*
* @v netdev Network device
+ * @v priv Private data
*/
-static void xsigo_net_notify ( struct net_device *netdev ) {
+static void xsigo_net_notify ( struct net_device *netdev,
+ void *priv __unused ) {
struct xsigo_device *xdev;
struct ib_device *ibdev;
struct xsigo_manager *xcm;
diff --git a/src/net/ipv6.c b/src/net/ipv6.c
index ef5e51da..8ee0804d 100644
--- a/src/net/ipv6.c
+++ b/src/net/ipv6.c
@@ -1212,50 +1212,33 @@ static struct settings_operations ipv6_settings_operations = {
.fetch = ipv6_fetch,
};
-/** IPv6 link-local address settings */
-struct ipv6_settings {
- /** Reference counter */
- struct refcnt refcnt;
- /** Settings interface */
- struct settings settings;
-};
-
/**
* Register IPv6 link-local address settings
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int ipv6_register_settings ( struct net_device *netdev ) {
+static int ipv6_register_settings ( struct net_device *netdev, void *priv ) {
struct settings *parent = netdev_settings ( netdev );
- struct ipv6_settings *ipv6set;
+ struct settings *settings = priv;
int rc;
- /* Allocate and initialise structure */
- ipv6set = zalloc ( sizeof ( *ipv6set ) );
- if ( ! ipv6set ) {
- rc = -ENOMEM;
- goto err_alloc;
- }
- ref_init ( &ipv6set->refcnt, NULL );
- settings_init ( &ipv6set->settings, &ipv6_settings_operations,
- &ipv6set->refcnt, &ipv6_settings_scope );
- ipv6set->settings.order = IPV6_ORDER_LINK_LOCAL;
-
- /* Register settings */
- if ( ( rc = register_settings ( &ipv6set->settings, parent,
+ /* Initialise and register settings */
+ settings_init ( settings, &ipv6_settings_operations,
+ &netdev->refcnt, &ipv6_settings_scope );
+ settings->order = IPV6_ORDER_LINK_LOCAL;
+ if ( ( rc = register_settings ( settings, parent,
IPV6_SETTINGS_NAME ) ) != 0 )
- goto err_register;
+ return rc;
- err_register:
- ref_put ( &ipv6set->refcnt );
- err_alloc:
- return rc;
+ return 0;
}
/** IPv6 network device driver */
struct net_driver ipv6_driver __net_driver = {
.name = "IPv6",
+ .priv_len = sizeof ( struct settings ),
.probe = ipv6_register_settings,
};
diff --git a/src/net/lldp.c b/src/net/lldp.c
index 72e3ecdf..a854d0ac 100644
--- a/src/net/lldp.c
+++ b/src/net/lldp.c
@@ -40,12 +40,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** An LLDP settings block */
struct lldp_settings {
- /** Reference counter */
- struct refcnt refcnt;
/** Settings interface */
struct settings settings;
- /** List of LLDP settings blocks */
- struct list_head list;
/** Name */
const char *name;
/** LLDP data */
@@ -54,45 +50,12 @@ struct lldp_settings {
size_t len;
};
+/* Forward declaration */
+struct net_driver lldp_driver __net_driver;
+
/** LLDP settings scope */
static const struct settings_scope lldp_settings_scope;
-/** List of LLDP settings blocks */
-static LIST_HEAD ( lldp_settings );
-
-/**
- * Free LLDP settings block
- *
- * @v refcnt Reference counter
- */
-static void lldp_free ( struct refcnt *refcnt ) {
- struct lldp_settings *lldpset =
- container_of ( refcnt, struct lldp_settings, refcnt );
-
- DBGC ( lldpset, "LLDP %s freed\n", lldpset->name );
- list_del ( &lldpset->list );
- free ( lldpset->data );
- free ( lldpset );
-}
-
-/**
- * Find LLDP settings block
- *
- * @v netdev Network device
- * @ret lldpset LLDP settings block
- */
-static struct lldp_settings * lldp_find ( struct net_device *netdev ) {
- struct lldp_settings *lldpset;
-
- /* Find matching LLDP settings block */
- list_for_each_entry ( lldpset, &lldp_settings, list ) {
- if ( netdev_settings ( netdev ) == lldpset->settings.parent )
- return lldpset;
- }
-
- return NULL;
-}
-
/**
* Check applicability of LLDP setting
*
@@ -246,13 +209,7 @@ static int lldp_rx ( struct io_buffer *iobuf, struct net_device *netdev,
int rc;
/* Find matching LLDP settings block */
- lldpset = lldp_find ( netdev );
- if ( ! lldpset ) {
- DBGC ( netdev, "LLDP %s has no \"%s\" settings block\n",
- netdev->name, LLDP_SETTINGS_NAME );
- rc = -ENOENT;
- goto err_find;
- }
+ lldpset = netdev_priv ( netdev, &lldp_driver );
/* Create trimmed copy of received LLDP data */
len = iob_len ( iobuf );
@@ -280,7 +237,6 @@ static int lldp_rx ( struct io_buffer *iobuf, struct net_device *netdev,
free ( data );
err_alloc:
- err_find:
free_iob ( iobuf );
return rc;
}
@@ -296,26 +252,21 @@ struct net_protocol lldp_protocol __net_protocol = {
* Create LLDP settings block
*
* @v netdev Network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int lldp_probe ( struct net_device *netdev ) {
- struct lldp_settings *lldpset;
+static int lldp_probe ( struct net_device *netdev, void *priv ) {
+ struct lldp_settings *lldpset = priv;
int rc;
- /* Allocate LLDP settings block */
- lldpset = zalloc ( sizeof ( *lldpset ) );
- if ( ! lldpset ) {
- rc = -ENOMEM;
- goto err_alloc;
- }
- ref_init ( &lldpset->refcnt, lldp_free );
+ /* Initialise LLDP settings block */
settings_init ( &lldpset->settings, &lldp_settings_operations,
- &lldpset->refcnt, &lldp_settings_scope );
- list_add_tail ( &lldpset->list, &lldp_settings );
+ &netdev->refcnt, &lldp_settings_scope );
lldpset->name = netdev->name;
/* Register settings */
- if ( ( rc = register_settings ( &lldpset->settings, netdev_settings ( netdev ),
+ if ( ( rc = register_settings ( &lldpset->settings,
+ netdev_settings ( netdev ),
LLDP_SETTINGS_NAME ) ) != 0 ) {
DBGC ( lldpset, "LLDP %s could not register settings: %s\n",
lldpset->name, strerror ( rc ) );
@@ -323,18 +274,36 @@ static int lldp_probe ( struct net_device *netdev ) {
}
DBGC ( lldpset, "LLDP %s registered\n", lldpset->name );
- ref_put ( &lldpset->refcnt );
return 0;
unregister_settings ( &lldpset->settings );
err_register:
- ref_put ( &lldpset->refcnt );
- err_alloc:
+ assert ( lldpset->data == NULL );
return rc;
}
+/**
+ * Remove LLDP settings block
+ *
+ * @v netdev Network device
+ * @v priv Private data
+ */
+static void lldp_remove ( struct net_device *netdev __unused, void *priv ) {
+ struct lldp_settings *lldpset = priv;
+
+ /* Unregister settings */
+ unregister_settings ( &lldpset->settings );
+ DBGC ( lldpset, "LLDP %s unregistered\n", lldpset->name );
+
+ /* Free any LLDP data */
+ free ( lldpset->data );
+ lldpset->data = NULL;
+}
+
/** LLDP driver */
struct net_driver lldp_driver __net_driver = {
.name = "LLDP",
+ .priv_len = sizeof ( struct lldp_settings ),
.probe = lldp_probe,
+ .remove = lldp_remove,
};
diff --git a/src/net/neighbour.c b/src/net/neighbour.c
index 7f66d999..13a8bc3b 100644
--- a/src/net/neighbour.c
+++ b/src/net/neighbour.c
@@ -383,8 +383,9 @@ int neighbour_define ( struct net_device *netdev,
* Update neighbour cache on network device state change or removal
*
* @v netdev Network device
+ * @v priv Private data
*/
-static void neighbour_flush ( struct net_device *netdev ) {
+static void neighbour_flush ( struct net_device *netdev, void *priv __unused ) {
struct neighbour *neighbour;
struct neighbour *tmp;
diff --git a/src/net/netdevice.c b/src/net/netdevice.c
index 07961bf2..a9ed1813 100644
--- a/src/net/netdevice.c
+++ b/src/net/netdevice.c
@@ -110,16 +110,63 @@ static int netdev_has_ll_addr ( struct net_device *netdev ) {
}
/**
+ * Get offset of network device driver private data
+ *
+ * @v driver Upper-layer driver, or NULL for device driver
+ * @ret offset Offset of driver private data
+ */
+static size_t netdev_priv_offset ( struct net_driver *driver ) {
+ struct net_device *netdev;
+ unsigned int num_configs;
+ size_t offset;
+
+ /* Allow space for network device */
+ offset = sizeof ( *netdev );
+
+ /* Allow space for configurations */
+ num_configs = table_num_entries ( NET_DEVICE_CONFIGURATORS );
+ offset += ( num_configs * sizeof ( netdev->configs[0] ) );
+
+ /* Place variable-length device driver private data at end */
+ if ( ! driver )
+ driver = table_end ( NET_DRIVERS );
+
+ /* Allow space for preceding upper-layer drivers' private data */
+ for_each_table_entry_continue_reverse ( driver, NET_DRIVERS ) {
+ offset += driver->priv_len;
+ }
+
+ /* Sanity check */
+ assert ( ( offset & ( sizeof ( void * ) - 1 ) ) == 0 );
+
+ return offset;
+}
+
+/**
+ * Get network device driver private data
+ *
+ * @v netdev Network device
+ * @v driver Upper-layer driver, or NULL for device driver
+ * @ret priv Driver private data
+ */
+void * netdev_priv ( struct net_device *netdev, struct net_driver *driver ) {
+
+ return ( ( ( void * ) netdev ) + netdev_priv_offset ( driver ) );
+}
+
+/**
* Notify drivers of network device or link state change
*
* @v netdev Network device
*/
static void netdev_notify ( struct net_device *netdev ) {
struct net_driver *driver;
+ void *priv;
for_each_table_entry ( driver, NET_DRIVERS ) {
+ priv = netdev_priv ( netdev, driver );
if ( driver->notify )
- driver->notify ( netdev );
+ driver->notify ( netdev, priv );
}
}
@@ -656,7 +703,7 @@ static void free_netdev ( struct refcnt *refcnt ) {
struct net_device *netdev =
container_of ( refcnt, struct net_device, refcnt );
- stop_timer ( &netdev->link_block );
+ assert ( ! timer_running ( &netdev->link_block ) );
netdev_tx_flush ( netdev );
netdev_rx_flush ( netdev );
clear_settings ( netdev_settings ( netdev ) );
@@ -675,14 +722,8 @@ struct net_device * alloc_netdev ( size_t priv_len ) {
struct net_device *netdev;
struct net_device_configurator *configurator;
struct net_device_configuration *config;
- unsigned int num_configs;
- size_t confs_len;
- size_t total_len;
- num_configs = table_num_entries ( NET_DEVICE_CONFIGURATORS );
- confs_len = ( num_configs * sizeof ( netdev->configs[0] ) );
- total_len = ( sizeof ( *netdev ) + confs_len + priv_len );
- netdev = zalloc ( total_len );
+ netdev = zalloc ( netdev_priv_offset ( NULL ) + priv_len );
if ( netdev ) {
ref_init ( &netdev->refcnt, free_netdev );
netdev->link_rc = -EUNKNOWN_LINK_STATUS;
@@ -701,8 +742,7 @@ struct net_device * alloc_netdev ( size_t priv_len ) {
&netdev->refcnt );
config++;
}
- netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) +
- confs_len );
+ netdev->priv = netdev_priv ( netdev, NULL );
}
return netdev;
}
@@ -722,6 +762,7 @@ int register_netdev ( struct net_device *netdev ) {
struct net_device *duplicate;
unsigned int i;
uint32_t seed;
+ void *priv;
int rc;
/* Set initial link-layer address, if not already set */
@@ -784,7 +825,9 @@ int register_netdev ( struct net_device *netdev ) {
/* Probe device */
for_each_table_entry ( driver, NET_DRIVERS ) {
- if ( driver->probe && ( rc = driver->probe ( netdev ) ) != 0 ) {
+ priv = netdev_priv ( netdev, driver );
+ if ( driver->probe &&
+ ( rc = driver->probe ( netdev, priv ) ) != 0 ) {
DBGC ( netdev, "NETDEV %s could not add %s device: "
"%s\n", netdev->name, driver->name,
strerror ( rc ) );
@@ -796,8 +839,9 @@ int register_netdev ( struct net_device *netdev ) {
err_probe:
for_each_table_entry_continue_reverse ( driver, NET_DRIVERS ) {
+ priv = netdev_priv ( netdev, driver );
if ( driver->remove )
- driver->remove ( netdev );
+ driver->remove ( netdev, priv );
}
clear_settings ( netdev_settings ( netdev ) );
unregister_settings ( netdev_settings ( netdev ) );
@@ -879,6 +923,9 @@ void netdev_close ( struct net_device *netdev ) {
/* Close the device */
netdev->op->close ( netdev );
+ /* Stop link block timer */
+ stop_timer ( &netdev->link_block );
+
/* Flush TX and RX queues */
netdev_tx_flush ( netdev );
netdev_rx_flush ( netdev );
@@ -893,14 +940,16 @@ void netdev_close ( struct net_device *netdev ) {
*/
void unregister_netdev ( struct net_device *netdev ) {
struct net_driver *driver;
+ void *priv;
/* Ensure device is closed */
netdev_close ( netdev );
/* Remove device */
for_each_table_entry_reverse ( driver, NET_DRIVERS ) {
+ priv = netdev_priv ( netdev, driver );
if ( driver->remove )
- driver->remove ( netdev );
+ driver->remove ( netdev, priv );
}
/* Unregister per-netdev configuration settings */
diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c
index bd2c4a19..8e2e97f1 100644
--- a/src/net/udp/dhcp.c
+++ b/src/net/udp/dhcp.c
@@ -91,9 +91,10 @@ static uint8_t dhcp_request_options_data[] = {
DHCP_PARAMETER_REQUEST_LIST,
DHCP_OPTION ( DHCP_SUBNET_MASK, DHCP_ROUTERS, DHCP_DNS_SERVERS,
DHCP_LOG_SERVERS, DHCP_HOST_NAME, DHCP_DOMAIN_NAME,
- DHCP_ROOT_PATH, DHCP_MTU, DHCP_VENDOR_ENCAP,
- DHCP_VENDOR_CLASS_ID, DHCP_TFTP_SERVER_NAME,
- DHCP_BOOTFILE_NAME, DHCP_DOMAIN_SEARCH,
+ DHCP_ROOT_PATH, DHCP_MTU, DHCP_NTP_SERVERS,
+ DHCP_VENDOR_ENCAP, DHCP_VENDOR_CLASS_ID,
+ DHCP_TFTP_SERVER_NAME, DHCP_BOOTFILE_NAME,
+ DHCP_DOMAIN_SEARCH,
128, 129, 130, 131, 132, 133, 134, 135, /* for PXE */
DHCP_EB_ENCAP, DHCP_ISCSI_INITIATOR_IQN ),
DHCP_END
diff --git a/src/net/udp/ntp.c b/src/net/udp/ntp.c
index 11f8ccc0..55923357 100644
--- a/src/net/udp/ntp.c
+++ b/src/net/udp/ntp.c
@@ -36,6 +36,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/timer.h>
#include <ipxe/time.h>
#include <ipxe/tcpip.h>
+#include <ipxe/dhcp.h>
+#include <ipxe/settings.h>
#include <ipxe/ntp.h>
/** @file
@@ -273,3 +275,11 @@ int start_ntp ( struct interface *job, const char *hostname ) {
err_alloc:
return rc;
}
+
+/** IPv4 NTP server setting */
+const struct setting ntp_setting __setting ( SETTING_IP4_EXTRA, ntp ) = {
+ .name = "ntp",
+ .description = "NTP server",
+ .tag = DHCP_NTP_SERVERS,
+ .type = &setting_type_ipv4,
+};
diff --git a/src/net/vlan.c b/src/net/vlan.c
index d73a9571..c61bb850 100644
--- a/src/net/vlan.c
+++ b/src/net/vlan.c
@@ -470,9 +470,10 @@ void vlan_auto ( const void *ll_addr, unsigned int tag ) {
* Create automatic VLAN device
*
* @v trunk Trunk network device
+ * @v priv Private data
* @ret rc Return status code
*/
-static int vlan_probe ( struct net_device *trunk ) {
+static int vlan_probe ( struct net_device *trunk, void *priv __unused ) {
int rc;
/* Do nothing unless an automatic VLAN exists */
@@ -498,8 +499,9 @@ static int vlan_probe ( struct net_device *trunk ) {
* Handle trunk network device link state change
*
* @v trunk Trunk network device
+ * @v priv Private data
*/
-static void vlan_notify ( struct net_device *trunk ) {
+static void vlan_notify ( struct net_device *trunk, void *priv __unused ) {
struct net_device *netdev;
struct vlan_device *vlan;
@@ -538,8 +540,9 @@ static int vlan_remove_first ( struct net_device *trunk ) {
* Destroy all VLAN devices for a given trunk
*
* @v trunk Trunk network device
+ * @v priv Private data
*/
-static void vlan_remove ( struct net_device *trunk ) {
+static void vlan_remove ( struct net_device *trunk, void *priv __unused ) {
/* Remove all VLAN devices attached to this trunk, safe
* against arbitrary net device removal.
diff --git a/src/tests/rsa_test.c b/src/tests/rsa_test.c
index c5b587ca..46894f60 100644
--- a/src/tests/rsa_test.c
+++ b/src/tests/rsa_test.c
@@ -206,7 +206,7 @@ struct rsa_signature_test {
sizeof ( bad_signature ) ); \
} while ( 0 )
-/** "Hello world" encryption and decryption test */
+/** "Hello world" encryption and decryption test (traditional PKCS#1 key) */
RSA_ENCRYPT_DECRYPT_TEST ( hw_test,
PRIVATE ( 0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00,
0xd2, 0xf1, 0x04, 0x67, 0xf6, 0x2c, 0x96, 0x07, 0xa6, 0xbd,
@@ -260,6 +260,63 @@ RSA_ENCRYPT_DECRYPT_TEST ( hw_test,
0x88, 0x4f, 0xec, 0x43, 0x9c, 0xed, 0xb3, 0xf2, 0x19, 0x89,
0x38, 0x43, 0xf9, 0x41 ) );
+/** "Hello world" encryption and decryption test (PKCS#8 key) */
+RSA_ENCRYPT_DECRYPT_TEST ( hw_test_pkcs8,
+ PRIVATE ( 0x30, 0x82, 0x01, 0x55, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+ 0x05, 0x00, 0x04, 0x82, 0x01, 0x3f, 0x30, 0x82, 0x01, 0x3b,
+ 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, 0xd2, 0xf1, 0x04, 0x67,
+ 0xf6, 0x2c, 0x96, 0x07, 0xa6, 0xbd, 0x85, 0xac, 0xc1, 0x17,
+ 0x5d, 0xe8, 0xf0, 0x93, 0x94, 0x0c, 0x45, 0x67, 0x26, 0x67,
+ 0xde, 0x7e, 0xfb, 0xa8, 0xda, 0xbd, 0x07, 0xdf, 0xcf, 0x45,
+ 0x04, 0x6d, 0xbd, 0x69, 0x8b, 0xfb, 0xc1, 0x72, 0xc0, 0xfc,
+ 0x03, 0x04, 0xf2, 0x82, 0xc4, 0x7b, 0x6a, 0x3e, 0xec, 0x53,
+ 0x7a, 0xe3, 0x4e, 0xa8, 0xc9, 0xf9, 0x1f, 0x2a, 0x13, 0x0d,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x40, 0x49, 0xb8, 0x61,
+ 0xc9, 0xd3, 0x87, 0x11, 0x87, 0xeb, 0x06, 0x21, 0x49, 0x96,
+ 0xd2, 0x0b, 0xc7, 0xf5, 0x0c, 0x1e, 0x99, 0x8b, 0x47, 0xd9,
+ 0x6c, 0x43, 0x9e, 0x2d, 0x65, 0x7d, 0xcc, 0xc2, 0x8b, 0x1a,
+ 0x6f, 0x2b, 0x55, 0xbe, 0xb3, 0x9f, 0xd1, 0xe2, 0x9a, 0xde,
+ 0x1d, 0xac, 0xec, 0x67, 0xec, 0xa5, 0xbf, 0x9c, 0x30, 0xd6,
+ 0xf9, 0x0a, 0x1a, 0x48, 0xf3, 0xc2, 0x93, 0x3a, 0x17, 0x27,
+ 0x21, 0x02, 0x21, 0x00, 0xfc, 0x8d, 0xfb, 0xee, 0x8a, 0xaa,
+ 0x45, 0x19, 0x4b, 0xf0, 0x68, 0xb0, 0x02, 0x38, 0x3e, 0x03,
+ 0x6b, 0x24, 0x77, 0x20, 0xbd, 0x5e, 0x6c, 0x76, 0xdb, 0xc9,
+ 0xe1, 0x43, 0xa3, 0x40, 0x62, 0x6f, 0x02, 0x21, 0x00, 0xd5,
+ 0xd1, 0xb4, 0x4d, 0x03, 0x40, 0x69, 0x3f, 0x9a, 0xa7, 0x44,
+ 0x15, 0x28, 0x1e, 0xa5, 0x5f, 0xcf, 0x97, 0x21, 0x12, 0xb3,
+ 0xe6, 0x1c, 0x9a, 0x8d, 0xb7, 0xb4, 0x80, 0x3a, 0x9c, 0xb0,
+ 0x43, 0x02, 0x20, 0x71, 0xf0, 0xa0, 0xab, 0x82, 0xf5, 0xc4,
+ 0x8c, 0xe0, 0x1c, 0xcb, 0x2e, 0x35, 0x22, 0x28, 0xa0, 0x24,
+ 0x33, 0x64, 0x67, 0x69, 0xe7, 0xf2, 0xa9, 0x41, 0x09, 0x78,
+ 0x4e, 0xaa, 0x95, 0x3e, 0x93, 0x02, 0x21, 0x00, 0x85, 0xcc,
+ 0x4d, 0xd9, 0x0b, 0x39, 0xd9, 0x22, 0x75, 0xf2, 0x49, 0x46,
+ 0x3b, 0xee, 0xc1, 0x69, 0x6d, 0x0b, 0x93, 0x24, 0x92, 0xf2,
+ 0x61, 0xdf, 0xcc, 0xe2, 0xb1, 0xce, 0xb3, 0xde, 0xac, 0xe5,
+ 0x02, 0x21, 0x00, 0x9c, 0x23, 0x6a, 0x95, 0xa6, 0xfe, 0x1e,
+ 0xd8, 0x0c, 0x3f, 0x6e, 0xe6, 0x0a, 0xeb, 0x97, 0xd6, 0x36,
+ 0x1c, 0x80, 0xc1, 0x02, 0x87, 0x0d, 0x4d, 0xfe, 0x28, 0x02,
+ 0x1e, 0xde, 0xe1, 0xcc, 0x72 ),
+ PUBLIC ( 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00,
+ 0x30, 0x48, 0x02, 0x41, 0x00, 0xd2, 0xf1, 0x04, 0x67, 0xf6,
+ 0x2c, 0x96, 0x07, 0xa6, 0xbd, 0x85, 0xac, 0xc1, 0x17, 0x5d,
+ 0xe8, 0xf0, 0x93, 0x94, 0x0c, 0x45, 0x67, 0x26, 0x67, 0xde,
+ 0x7e, 0xfb, 0xa8, 0xda, 0xbd, 0x07, 0xdf, 0xcf, 0x45, 0x04,
+ 0x6d, 0xbd, 0x69, 0x8b, 0xfb, 0xc1, 0x72, 0xc0, 0xfc, 0x03,
+ 0x04, 0xf2, 0x82, 0xc4, 0x7b, 0x6a, 0x3e, 0xec, 0x53, 0x7a,
+ 0xe3, 0x4e, 0xa8, 0xc9, 0xf9, 0x1f, 0x2a, 0x13, 0x0d, 0x02,
+ 0x03, 0x01, 0x00, 0x01 ),
+ PLAINTEXT ( 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c,
+ 0x64, 0x0a ),
+ CIPHERTEXT ( 0x39, 0xff, 0x5c, 0x54, 0x65, 0x3e, 0x6a, 0xab, 0xc0, 0x62,
+ 0x91, 0xb2, 0xbf, 0x1d, 0x73, 0x5b, 0xd5, 0x4c, 0xbd, 0x16,
+ 0x0f, 0x24, 0xc9, 0xf5, 0xa7, 0xdd, 0x94, 0xd6, 0xf8, 0xae,
+ 0xd3, 0xa0, 0x9f, 0x4d, 0xff, 0x8d, 0x81, 0x34, 0x47, 0xff,
+ 0x2a, 0x87, 0x96, 0xd3, 0x17, 0x5d, 0x93, 0x4d, 0x7b, 0x27,
+ 0x88, 0x4f, 0xec, 0x43, 0x9c, 0xed, 0xb3, 0xf2, 0x19, 0x89,
+ 0x38, 0x43, 0xf9, 0x41 ) );
+
/** Random message MD5 signature test */
RSA_SIGNATURE_TEST ( md5_test,
PRIVATE ( 0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00,
@@ -486,6 +543,7 @@ RSA_SIGNATURE_TEST ( sha256_test,
static void rsa_test_exec ( void ) {
rsa_encrypt_decrypt_ok ( &hw_test );
+ rsa_encrypt_decrypt_ok ( &hw_test_pkcs8 );
rsa_signature_ok ( &md5_test );
rsa_signature_ok ( &sha1_test );
rsa_signature_ok ( &sha256_test );
diff --git a/src/usr/imgmgmt.c b/src/usr/imgmgmt.c
index b7fc8293..92bf236f 100644
--- a/src/usr/imgmgmt.c
+++ b/src/usr/imgmgmt.c
@@ -156,15 +156,21 @@ int imgacquire ( const char *name_uri, unsigned long timeout,
* @v image Executable/loadable image
*/
void imgstat ( struct image *image ) {
+ struct image_tag *tag;
+
printf ( "%s : %zd bytes", image->name, image->len );
if ( image->type )
printf ( " [%s]", image->type->name );
+ for_each_table_entry ( tag, IMAGE_TAGS ) {
+ if ( tag->image == image )
+ printf ( " [%s]", tag->name );
+ }
if ( image->flags & IMAGE_TRUSTED )
printf ( " [TRUSTED]" );
- if ( image->flags & IMAGE_SELECTED )
- printf ( " [SELECTED]" );
if ( image->flags & IMAGE_AUTO_UNREGISTER )
printf ( " [AUTOFREE]" );
+ if ( image->flags & IMAGE_HIDDEN )
+ printf ( " [HIDDEN]" );
if ( image->cmdline )
printf ( " \"%s\"", image->cmdline );
printf ( "\n" );
diff --git a/src/usr/shimmgmt.c b/src/usr/shimmgmt.c
new file mode 100644
index 00000000..6ac1ac35
--- /dev/null
+++ b/src/usr/shimmgmt.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2023 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/efi_shim.h>
+#include <usr/shimmgmt.h>
+
+/** @file
+ *
+ * EFI shim management
+ *
+ */
+
+/**
+ * Set shim image
+ *
+ * @v image Shim image, or NULL to clear shim
+ * @v require_loader Require use of a third party loader
+ * @v allow_pxe Allow use of PXE base code
+ * @v allow_sbat Allow SBAT variable access
+ * @ret rc Return status code
+ */
+int shim ( struct image *image, int require_loader, int allow_pxe,
+ int allow_sbat ) {
+
+ /* Record (or clear) shim image */
+ image_tag ( image, &efi_shim );
+
+ /* Avoid including image in constructed initrd */
+ if ( image )
+ image_hide ( image );
+
+ /* Record configuration */
+ efi_shim_require_loader = require_loader;
+ efi_shim_allow_pxe = allow_pxe;
+ efi_shim_allow_sbat = allow_sbat;
+
+ return 0;
+}
diff --git a/src/util/elf2efi.c b/src/util/elf2efi.c
index cea9abf8..5b3e785f 100644
--- a/src/util/elf2efi.c
+++ b/src/util/elf2efi.c
@@ -168,6 +168,9 @@
*/
#define EFI_IMAGE_ALIGN 0x1000
+/** Number of data directory entries */
+#define NUMBER_OF_DIRECTORY_ENTRIES 8
+
struct elf_file {
void *data;
size_t len;
@@ -178,6 +181,7 @@ struct pe_section {
struct pe_section *next;
EFI_IMAGE_SECTION_HEADER hdr;
void ( * fixup ) ( struct pe_section *section );
+ int hidden;
uint8_t contents[0];
};
@@ -191,7 +195,6 @@ struct pe_relocs {
struct pe_header {
EFI_IMAGE_DOS_HEADER dos;
- uint8_t padding[128];
EFI_IMAGE_NT_HEADERS nt;
};
@@ -205,7 +208,11 @@ static struct pe_header efi_pe_header = {
.FileHeader = {
.TimeDateStamp = 0x10d1a884,
.SizeOfOptionalHeader =
- sizeof ( efi_pe_header.nt.OptionalHeader ),
+ ( sizeof ( efi_pe_header.nt.OptionalHeader ) -
+ ( ( EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES -
+ NUMBER_OF_DIRECTORY_ENTRIES ) *
+ sizeof ( efi_pe_header.nt.OptionalHeader.
+ DataDirectory[0] ) ) ),
.Characteristics = ( EFI_IMAGE_FILE_DLL |
EFI_IMAGE_FILE_MACHINE |
EFI_IMAGE_FILE_EXECUTABLE_IMAGE ),
@@ -218,15 +225,17 @@ static struct pe_header efi_pe_header = {
.FileAlignment = EFI_FILE_ALIGN,
.SizeOfImage = EFI_IMAGE_ALIGN,
.SizeOfHeaders = sizeof ( efi_pe_header ),
- .NumberOfRvaAndSizes =
- EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES,
+ .NumberOfRvaAndSizes = NUMBER_OF_DIRECTORY_ENTRIES,
},
},
};
/** Command-line options */
struct options {
+ /** PE32+ subsystem type */
unsigned int subsystem;
+ /** Create hybrid BIOS/UEFI binary */
+ int hybrid;
};
/**
@@ -633,10 +642,12 @@ static struct pe_section * process_section ( struct elf_file *elf,
/* Update RVA limits */
start = new->hdr.VirtualAddress;
end = ( start + new->hdr.Misc.VirtualSize );
- if ( ( ! *applicable_start ) || ( *applicable_start >= start ) )
- *applicable_start = start;
- if ( *applicable_end < end )
- *applicable_end = end;
+ if ( ! new->hidden ) {
+ if ( ( ! *applicable_start ) || ( *applicable_start >= start ) )
+ *applicable_start = start;
+ if ( *applicable_end < end )
+ *applicable_end = end;
+ }
if ( data_start < code_end )
data_start = code_end;
if ( data_mid < data_start )
@@ -656,8 +667,11 @@ static struct pe_section * process_section ( struct elf_file *elf,
( data_end - data_mid );
/* Update remaining file header fields */
- pe_header->nt.FileHeader.NumberOfSections++;
- pe_header->nt.OptionalHeader.SizeOfHeaders += sizeof ( new->hdr );
+ if ( ! new->hidden ) {
+ pe_header->nt.FileHeader.NumberOfSections++;
+ pe_header->nt.OptionalHeader.SizeOfHeaders +=
+ sizeof ( new->hdr );
+ }
pe_header->nt.OptionalHeader.SizeOfImage =
efi_image_align ( data_end );
@@ -673,10 +687,12 @@ static struct pe_section * process_section ( struct elf_file *elf,
* @v nsyms Number of symbol table entries
* @v rel Relocation record
* @v pe_reltab PE relocation table to fill in
+ * @v opts Options
*/
static void process_reloc ( struct elf_file *elf, const Elf_Shdr *shdr,
const Elf_Sym *syms, unsigned int nsyms,
- const Elf_Rel *rel, struct pe_relocs **pe_reltab ) {
+ const Elf_Rel *rel, struct pe_relocs **pe_reltab,
+ struct options *opts ) {
unsigned int type = ELF_R_TYPE ( rel->r_info );
unsigned int sym = ELF_R_SYM ( rel->r_info );
unsigned int mrel = ELF_MREL ( elf->ehdr->e_machine, type );
@@ -739,6 +755,15 @@ static void process_reloc ( struct elf_file *elf, const Elf_Shdr *shdr,
* loaded.
*/
break;
+ case ELF_MREL ( EM_X86_64, R_X86_64_32 ) :
+ /* Ignore 32-bit relocations in a hybrid
+ * 32-bit BIOS and 64-bit UEFI binary,
+ * otherwise fall through to treat as an
+ * unknown type.
+ */
+ if ( opts->hybrid )
+ break;
+ /* fallthrough */
default:
eprintf ( "Unrecognised relocation type %d\n", type );
exit ( 1 );
@@ -753,9 +778,11 @@ static void process_reloc ( struct elf_file *elf, const Elf_Shdr *shdr,
* @v shdr ELF section header
* @v stride Relocation record size
* @v pe_reltab PE relocation table to fill in
+ * @v opts Options
*/
static void process_relocs ( struct elf_file *elf, const Elf_Shdr *shdr,
- size_t stride, struct pe_relocs **pe_reltab ) {
+ size_t stride, struct pe_relocs **pe_reltab,
+ struct options *opts ) {
const Elf_Shdr *symtab;
const Elf_Sym *syms;
const Elf_Rel *rel;
@@ -773,7 +800,7 @@ static void process_relocs ( struct elf_file *elf, const Elf_Shdr *shdr,
rel = ( elf->data + shdr->sh_offset );
nrels = ( shdr->sh_size / stride );
for ( i = 0 ; i < nrels ; i++ ) {
- process_reloc ( elf, shdr, syms, nsyms, rel, pe_reltab );
+ process_reloc ( elf, shdr, syms, nsyms, rel, pe_reltab, opts );
rel = ( ( ( const void * ) rel ) + stride );
}
}
@@ -914,6 +941,7 @@ static void write_pe_file ( struct pe_header *pe_header,
FILE *pe ) {
struct pe_section *section;
unsigned long fpos = 0;
+ unsigned int count = 0;
/* Align length of headers */
fpos = pe_header->nt.OptionalHeader.SizeOfHeaders =
@@ -931,19 +959,26 @@ static void write_pe_file ( struct pe_header *pe_header,
}
/* Write file header */
- if ( fwrite ( pe_header, sizeof ( *pe_header ), 1, pe ) != 1 ) {
+ if ( fwrite ( pe_header,
+ ( offsetof ( typeof ( *pe_header ), nt.OptionalHeader ) +
+ pe_header->nt.FileHeader.SizeOfOptionalHeader ),
+ 1, pe ) != 1 ) {
perror ( "Could not write PE header" );
exit ( 1 );
}
/* Write section headers */
for ( section = pe_sections ; section ; section = section->next ) {
+ if ( section->hidden )
+ continue;
if ( fwrite ( &section->hdr, sizeof ( section->hdr ),
1, pe ) != 1 ) {
perror ( "Could not write section header" );
exit ( 1 );
}
+ count++;
}
+ assert ( count == pe_header->nt.FileHeader.NumberOfSections );
/* Write sections */
for ( section = pe_sections ; section ; section = section->next ) {
@@ -969,6 +1004,7 @@ static void write_pe_file ( struct pe_header *pe_header,
*
* @v elf_name ELF file name
* @v pe_name PE file name
+ * @v opts Options
*/
static void elf2pe ( const char *elf_name, const char *pe_name,
struct options *opts ) {
@@ -1012,13 +1048,13 @@ static void elf2pe ( const char *elf_name, const char *pe_name,
/* Process .rel relocations */
process_relocs ( &elf, shdr, sizeof ( Elf_Rel ),
- &pe_reltab );
+ &pe_reltab, opts );
} else if ( shdr->sh_type == SHT_RELA ) {
/* Process .rela relocations */
process_relocs ( &elf, shdr, sizeof ( Elf_Rela ),
- &pe_reltab );
+ &pe_reltab, opts );
}
}
@@ -1071,11 +1107,12 @@ static int parse_options ( const int argc, char **argv,
int option_index = 0;
static struct option long_options[] = {
{ "subsystem", required_argument, NULL, 's' },
+ { "hybrid", no_argument, NULL, 'H' },
{ "help", 0, NULL, 'h' },
{ 0, 0, 0, 0 }
};
- if ( ( c = getopt_long ( argc, argv, "s:h",
+ if ( ( c = getopt_long ( argc, argv, "s:Hh",
long_options,
&option_index ) ) == -1 ) {
break;
@@ -1090,6 +1127,9 @@ static int parse_options ( const int argc, char **argv,
exit ( 2 );
}
break;
+ case 'H':
+ opts->hybrid = 1;
+ break;
case 'h':
print_help ( argv[0] );
exit ( 0 );