summaryrefslogtreecommitdiff
path: root/gpxe/src/include
diff options
context:
space:
mode:
Diffstat (limited to 'gpxe/src/include')
-rw-r--r--gpxe/src/include/.gitignore1
-rw-r--r--gpxe/src/include/alloca.h25
-rw-r--r--gpxe/src/include/assert.h65
-rw-r--r--gpxe/src/include/big_bswap.h33
-rw-r--r--gpxe/src/include/bootp.h230
-rw-r--r--gpxe/src/include/btext.h62
-rw-r--r--gpxe/src/include/byteswap.h22
-rw-r--r--gpxe/src/include/cmdline.h8
-rw-r--r--gpxe/src/include/cmdlinelib.h99
-rw-r--r--gpxe/src/include/cmdlist.h18
-rw-r--r--gpxe/src/include/coff.h73
-rw-r--r--gpxe/src/include/compiler.h357
-rw-r--r--gpxe/src/include/console.h114
-rw-r--r--gpxe/src/include/cpu.h6
-rw-r--r--gpxe/src/include/ctype.h28
-rw-r--r--gpxe/src/include/curses.h753
-rw-r--r--gpxe/src/include/debug.h28
-rw-r--r--gpxe/src/include/dhcp.h12
-rw-r--r--gpxe/src/include/elf.h236
-rw-r--r--gpxe/src/include/endian.h19
-rw-r--r--gpxe/src/include/errno.h508
-rw-r--r--gpxe/src/include/etherboot.h42
-rw-r--r--gpxe/src/include/fs.h41
-rw-r--r--gpxe/src/include/getopt.h92
-rw-r--r--gpxe/src/include/gpxe/abft.h35
-rw-r--r--gpxe/src/include/gpxe/acpi.h41
-rw-r--r--gpxe/src/include/gpxe/aes.h8
-rw-r--r--gpxe/src/include/gpxe/ansiesc.h118
-rw-r--r--gpxe/src/include/gpxe/aoe.h126
-rw-r--r--gpxe/src/include/gpxe/arp.h41
-rw-r--r--gpxe/src/include/gpxe/asn1.h32
-rw-r--r--gpxe/src/include/gpxe/async.h228
-rw-r--r--gpxe/src/include/gpxe/ata.h205
-rw-r--r--gpxe/src/include/gpxe/bitbash.h50
-rw-r--r--gpxe/src/include/gpxe/bitmap.h83
-rw-r--r--gpxe/src/include/gpxe/bitops.h27
-rw-r--r--gpxe/src/include/gpxe/blockdev.h43
-rw-r--r--gpxe/src/include/gpxe/chap.h51
-rw-r--r--gpxe/src/include/gpxe/command.h22
-rw-r--r--gpxe/src/include/gpxe/cpio.h51
-rw-r--r--gpxe/src/include/gpxe/crypto.h116
-rw-r--r--gpxe/src/include/gpxe/device.h111
-rw-r--r--gpxe/src/include/gpxe/dhcp.h455
-rw-r--r--gpxe/src/include/gpxe/dhcpopts.h32
-rw-r--r--gpxe/src/include/gpxe/dhcppkt.h35
-rw-r--r--gpxe/src/include/gpxe/dns.h90
-rw-r--r--gpxe/src/include/gpxe/downloader.h17
-rw-r--r--gpxe/src/include/gpxe/editbox.h51
-rw-r--r--gpxe/src/include/gpxe/editstring.h31
-rw-r--r--gpxe/src/include/gpxe/eisa.h125
-rw-r--r--gpxe/src/include/gpxe/elf.h15
-rw-r--r--gpxe/src/include/gpxe/embedded.h9
-rw-r--r--gpxe/src/include/gpxe/errfile.h157
-rw-r--r--gpxe/src/include/gpxe/errortab.h19
-rw-r--r--gpxe/src/include/gpxe/ethernet.h33
-rw-r--r--gpxe/src/include/gpxe/fakedhcp.h21
-rw-r--r--gpxe/src/include/gpxe/features.h88
-rw-r--r--gpxe/src/include/gpxe/filter.h73
-rw-r--r--gpxe/src/include/gpxe/ftp.h13
-rw-r--r--gpxe/src/include/gpxe/hidemem.h23
-rw-r--r--gpxe/src/include/gpxe/hmac.h30
-rw-r--r--gpxe/src/include/gpxe/http.h21
-rw-r--r--gpxe/src/include/gpxe/i2c.h111
-rw-r--r--gpxe/src/include/gpxe/ibft.h300
-rw-r--r--gpxe/src/include/gpxe/icmp6.h57
-rw-r--r--gpxe/src/include/gpxe/if_arp.h100
-rw-r--r--gpxe/src/include/gpxe/if_ether.h33
-rw-r--r--gpxe/src/include/gpxe/image.h162
-rw-r--r--gpxe/src/include/gpxe/in.h94
-rw-r--r--gpxe/src/include/gpxe/infiniband.h751
-rw-r--r--gpxe/src/include/gpxe/init.h62
-rw-r--r--gpxe/src/include/gpxe/initrd.h14
-rw-r--r--gpxe/src/include/gpxe/interface.h56
-rw-r--r--gpxe/src/include/gpxe/iobuf.h189
-rw-r--r--gpxe/src/include/gpxe/ip.h95
-rw-r--r--gpxe/src/include/gpxe/ip6.h78
-rw-r--r--gpxe/src/include/gpxe/ipoib.h78
-rw-r--r--gpxe/src/include/gpxe/isa.h92
-rw-r--r--gpxe/src/include/gpxe/isa_ids.h49
-rw-r--r--gpxe/src/include/gpxe/isapnp.h273
-rw-r--r--gpxe/src/include/gpxe/iscsi.h654
-rw-r--r--gpxe/src/include/gpxe/job.h165
-rw-r--r--gpxe/src/include/gpxe/keys.h82
-rw-r--r--gpxe/src/include/gpxe/linebuf.h28
-rw-r--r--gpxe/src/include/gpxe/linux_compat.h25
-rw-r--r--gpxe/src/include/gpxe/list.h178
-rw-r--r--gpxe/src/include/gpxe/malloc.h57
-rw-r--r--gpxe/src/include/gpxe/mca.h103
-rw-r--r--gpxe/src/include/gpxe/md5.h22
-rw-r--r--gpxe/src/include/gpxe/memmap.h34
-rw-r--r--gpxe/src/include/gpxe/monojob.h15
-rw-r--r--gpxe/src/include/gpxe/ndp.h21
-rw-r--r--gpxe/src/include/gpxe/netdevice.h404
-rw-r--r--gpxe/src/include/gpxe/nvo.h53
-rw-r--r--gpxe/src/include/gpxe/nvs.h66
-rw-r--r--gpxe/src/include/gpxe/open.h95
-rw-r--r--gpxe/src/include/gpxe/pci.h356
-rw-r--r--gpxe/src/include/gpxe/pci_ids.h348
-rw-r--r--gpxe/src/include/gpxe/posix_io.h85
-rw-r--r--gpxe/src/include/gpxe/process.h75
-rw-r--r--gpxe/src/include/gpxe/profile.h78
-rw-r--r--gpxe/src/include/gpxe/ramdisk.h22
-rw-r--r--gpxe/src/include/gpxe/rarp.h14
-rw-r--r--gpxe/src/include/gpxe/refcnt.h44
-rw-r--r--gpxe/src/include/gpxe/resolv.h166
-rw-r--r--gpxe/src/include/gpxe/retry.h52
-rw-r--r--gpxe/src/include/gpxe/rsa.h10
-rw-r--r--gpxe/src/include/gpxe/scsi.h270
-rw-r--r--gpxe/src/include/gpxe/segment.h15
-rw-r--r--gpxe/src/include/gpxe/settings.h285
-rw-r--r--gpxe/src/include/gpxe/settings_ui.h14
-rw-r--r--gpxe/src/include/gpxe/sha1.h13
-rw-r--r--gpxe/src/include/gpxe/shell.h12
-rw-r--r--gpxe/src/include/gpxe/shell_banner.h12
-rw-r--r--gpxe/src/include/gpxe/socket.h95
-rw-r--r--gpxe/src/include/gpxe/spi.h239
-rw-r--r--gpxe/src/include/gpxe/spi_bit.h61
-rw-r--r--gpxe/src/include/gpxe/tables.h229
-rw-r--r--gpxe/src/include/gpxe/tcp.h306
-rw-r--r--gpxe/src/include/gpxe/tcpip.h118
-rw-r--r--gpxe/src/include/gpxe/tftp.h83
-rw-r--r--gpxe/src/include/gpxe/threewire.h89
-rw-r--r--gpxe/src/include/gpxe/timer.h41
-rw-r--r--gpxe/src/include/gpxe/tls.h171
-rw-r--r--gpxe/src/include/gpxe/uaccess.h27
-rw-r--r--gpxe/src/include/gpxe/udp.h47
-rw-r--r--gpxe/src/include/gpxe/umalloc.h17
-rw-r--r--gpxe/src/include/gpxe/uri.h139
-rw-r--r--gpxe/src/include/gpxe/uuid.h34
-rw-r--r--gpxe/src/include/gpxe/vsprintf.h71
-rw-r--r--gpxe/src/include/gpxe/xfer.h275
-rw-r--r--gpxe/src/include/i82365.h450
-rw-r--r--gpxe/src/include/igmp.h42
-rw-r--r--gpxe/src/include/lib.h42
-rw-r--r--gpxe/src/include/libgen.h7
-rw-r--r--gpxe/src/include/little_bswap.h33
-rw-r--r--gpxe/src/include/mii.h105
-rw-r--r--gpxe/src/include/nfs.h63
-rw-r--r--gpxe/src/include/nic.h272
-rw-r--r--gpxe/src/include/nmb.h22
-rw-r--r--gpxe/src/include/old_tcp.h37
-rw-r--r--gpxe/src/include/pc_kbd.h7
-rw-r--r--gpxe/src/include/pcmcia-opts.h23
-rw-r--r--gpxe/src/include/pcmcia.h156
-rw-r--r--gpxe/src/include/pxe.h151
-rw-r--r--gpxe/src/include/pxe_api.h1841
-rw-r--r--gpxe/src/include/pxe_types.h126
-rw-r--r--gpxe/src/include/readline/readline.h12
-rw-r--r--gpxe/src/include/stdarg.h10
-rw-r--r--gpxe/src/include/stddef.h18
-rw-r--r--gpxe/src/include/stdint.h24
-rw-r--r--gpxe/src/include/stdio.h45
-rw-r--r--gpxe/src/include/stdlib.h72
-rw-r--r--gpxe/src/include/string.h49
-rw-r--r--gpxe/src/include/strings.h63
-rw-r--r--gpxe/src/include/sys/time.h20
-rw-r--r--gpxe/src/include/sys_info.h33
-rw-r--r--gpxe/src/include/time.h22
-rw-r--r--gpxe/src/include/unistd.h31
-rw-r--r--gpxe/src/include/usr/aoeboot.h6
-rw-r--r--gpxe/src/include/usr/autoboot.h13
-rw-r--r--gpxe/src/include/usr/dhcpmgmt.h14
-rw-r--r--gpxe/src/include/usr/ifmgmt.h16
-rw-r--r--gpxe/src/include/usr/imgmgmt.h20
-rw-r--r--gpxe/src/include/usr/iscsiboot.h6
-rw-r--r--gpxe/src/include/usr/route.h12
166 files changed, 17970 insertions, 0 deletions
diff --git a/gpxe/src/include/.gitignore b/gpxe/src/include/.gitignore
new file mode 100644
index 00000000..de1598ef
--- /dev/null
+++ b/gpxe/src/include/.gitignore
@@ -0,0 +1 @@
+.buildserial.h
diff --git a/gpxe/src/include/alloca.h b/gpxe/src/include/alloca.h
new file mode 100644
index 00000000..08398fb3
--- /dev/null
+++ b/gpxe/src/include/alloca.h
@@ -0,0 +1,25 @@
+#ifndef _ALLOCA_H
+#define _ALLOCA_H
+
+/**
+ * @file
+ *
+ * Temporary memory allocation
+ *
+ */
+
+#include <stdint.h>
+
+/**
+ * Allocate temporary memory from the stack
+ *
+ * @v size Size to allocate
+ * @ret ptr Allocated memory
+ *
+ * This memory will be freed automatically when the containing
+ * function returns. There are several caveats regarding use of
+ * alloca(); use it only if you already know what they are.
+ */
+#define alloca(size) __builtin_alloca ( size )
+
+#endif /* _ALLOCA_H */
diff --git a/gpxe/src/include/assert.h b/gpxe/src/include/assert.h
new file mode 100644
index 00000000..93750a1e
--- /dev/null
+++ b/gpxe/src/include/assert.h
@@ -0,0 +1,65 @@
+#ifndef _ASSERT_H
+#define _ASSERT_H
+
+/** @file
+ *
+ * Assertions
+ *
+ * This file provides two assertion macros: assert() (for run-time
+ * assertions) and linker_assert() (for link-time assertions).
+ *
+ */
+
+#ifdef NDEBUG
+#define ASSERTING 0
+#else
+#define ASSERTING 1
+#endif
+
+/** printf() for assertions
+ *
+ * This function exists so that the assert() macro can expand to
+ * printf() calls without dragging the printf() prototype into scope.
+ *
+ * As far as the compiler is concerned, assert_printf() and printf() are
+ * completely unrelated calls; it's only at the assembly stage that
+ * references to the assert_printf symbol are collapsed into references
+ * to the printf symbol.
+ */
+extern int __attribute__ (( format ( printf, 1, 2 ) ))
+assert_printf ( const char *fmt, ... ) asm ( "printf" );
+
+/**
+ * Assert a condition at run-time.
+ *
+ * If the condition is not true, a debug message will be printed.
+ * Assertions only take effect in debug-enabled builds (see DBG()).
+ *
+ * @todo Make an assertion failure abort the program
+ *
+ */
+#define assert( condition ) \
+ do { \
+ if ( ASSERTING && ! (condition) ) { \
+ assert_printf ( "assert(%s) failed at %s line %d\n", \
+ #condition, __FILE__, __LINE__ ); \
+ } \
+ } while ( 0 )
+
+/**
+ * Assert a condition at link-time.
+ *
+ * If the condition is not true, the link will fail with an unresolved
+ * symbol (error_symbol).
+ *
+ * This macro is gPXE-specific. Do not use this macro in code
+ * intended to be portable.
+ *
+ */
+#define linker_assert( condition, error_symbol ) \
+ if ( ! (condition) ) { \
+ extern void error_symbol ( void ); \
+ error_symbol(); \
+ }
+
+#endif /* _ASSERT_H */
diff --git a/gpxe/src/include/big_bswap.h b/gpxe/src/include/big_bswap.h
new file mode 100644
index 00000000..3775fac1
--- /dev/null
+++ b/gpxe/src/include/big_bswap.h
@@ -0,0 +1,33 @@
+#ifndef ETHERBOOT_BIG_BSWAP_H
+#define ETHERBOOT_BIG_BSWAP_H
+
+#define ntohl(x) (x)
+#define htonl(x) (x)
+#define ntohs(x) (x)
+#define htons(x) (x)
+#define cpu_to_le64(x) __bswap_64(x)
+#define cpu_to_le32(x) __bswap_32(x)
+#define cpu_to_le16(x) __bswap_16(x)
+#define cpu_to_be64(x) (x)
+#define cpu_to_be32(x) (x)
+#define cpu_to_be16(x) (x)
+#define le64_to_cpu(x) __bswap_64(x)
+#define le32_to_cpu(x) __bswap_32(x)
+#define le16_to_cpu(x) __bswap_16(x)
+#define be64_to_cpu(x) (x)
+#define be32_to_cpu(x) (x)
+#define be16_to_cpu(x) (x)
+#define cpu_to_le64s(x) __bswap_64s(x)
+#define cpu_to_le32s(x) __bswap_32s(x)
+#define cpu_to_le16s(x) __bswap_16s(x)
+#define cpu_to_be64s(x) do {} while (0)
+#define cpu_to_be32s(x) do {} while (0)
+#define cpu_to_be16s(x) do {} while (0)
+#define le64_to_cpus(x) __bswap_64s(x)
+#define le32_to_cpus(x) __bswap_32s(x)
+#define le16_to_cpus(x) __bswap_16s(x)
+#define be64_to_cpus(x) do {} while (0)
+#define be32_to_cpus(x) do {} while (0)
+#define be16_to_cpus(x) do {} while (0)
+
+#endif /* ETHERBOOT_BIG_BSWAP_H */
diff --git a/gpxe/src/include/bootp.h b/gpxe/src/include/bootp.h
new file mode 100644
index 00000000..0e65477a
--- /dev/null
+++ b/gpxe/src/include/bootp.h
@@ -0,0 +1,230 @@
+#ifndef _BOOTP_H
+#define _BOOTP_H
+
+#ifdef ALTERNATE_DHCP_PORTS_1067_1068
+#undef NON_STANDARD_BOOTP_SERVER
+#define NON_STANDARD_BOOTP_SERVER 1067
+#undef NON_STANDARD_BOOTP_CLIENT
+#define NON_STANDARD_BOOTP_CLIENT 1068
+#endif
+
+#ifdef NON_STANDARD_BOOTP_SERVER
+#define BOOTP_SERVER NON_STANDARD_BOOTP_SERVER
+#else
+#define BOOTP_SERVER 67
+#endif
+#ifdef NON_STANDARD_BOOTP_CLIENT
+#define BOOTP_CLIENT NON_STANDARD_BOOTP_CLIENT
+#else
+#define BOOTP_CLIENT 68
+#endif
+#define PROXYDHCP_SERVER 4011 /* For PXE */
+
+#define BOOTP_REQUEST 1
+#define BOOTP_REPLY 2
+
+#define TAG_LEN(p) (*((p)+1))
+#define RFC1533_COOKIE 99, 130, 83, 99
+#define RFC1533_PAD 0
+#define RFC1533_NETMASK 1
+#define RFC1533_TIMEOFFSET 2
+#define RFC1533_GATEWAY 3
+#define RFC1533_TIMESERVER 4
+#define RFC1533_IEN116NS 5
+#define RFC1533_DNS 6
+#define RFC1533_LOGSERVER 7
+#define RFC1533_COOKIESERVER 8
+#define RFC1533_LPRSERVER 9
+#define RFC1533_IMPRESSSERVER 10
+#define RFC1533_RESOURCESERVER 11
+#define RFC1533_HOSTNAME 12
+#define RFC1533_BOOTFILESIZE 13
+#define RFC1533_MERITDUMPFILE 14
+#define RFC1533_DOMAINNAME 15
+#define RFC1533_SWAPSERVER 16
+#define RFC1533_ROOTPATH 17
+#define RFC1533_EXTENSIONPATH 18
+#define RFC1533_IPFORWARDING 19
+#define RFC1533_IPSOURCEROUTING 20
+#define RFC1533_IPPOLICYFILTER 21
+#define RFC1533_IPMAXREASSEMBLY 22
+#define RFC1533_IPTTL 23
+#define RFC1533_IPMTU 24
+#define RFC1533_IPMTUPLATEAU 25
+#define RFC1533_INTMTU 26
+#define RFC1533_INTLOCALSUBNETS 27
+#define RFC1533_INTBROADCAST 28
+#define RFC1533_INTICMPDISCOVER 29
+#define RFC1533_INTICMPRESPOND 30
+#define RFC1533_INTROUTEDISCOVER 31
+#define RFC1533_INTROUTESOLICIT 32
+#define RFC1533_INTSTATICROUTES 33
+#define RFC1533_LLTRAILERENCAP 34
+#define RFC1533_LLARPCACHETMO 35
+#define RFC1533_LLETHERNETENCAP 36
+#define RFC1533_TCPTTL 37
+#define RFC1533_TCPKEEPALIVETMO 38
+#define RFC1533_TCPKEEPALIVEGB 39
+#define RFC1533_NISDOMAIN 40
+#define RFC1533_NISSERVER 41
+#define RFC1533_NTPSERVER 42
+#define RFC1533_VENDOR 43
+#define RFC1533_NBNS 44
+#define RFC1533_NBDD 45
+#define RFC1533_NBNT 46
+#define RFC1533_NBSCOPE 47
+#define RFC1533_XFS 48
+#define RFC1533_XDM 49
+#ifndef NO_DHCP_SUPPORT
+#define RFC2132_REQ_ADDR 50
+#define RFC2132_MSG_TYPE 53
+#define RFC2132_SRV_ID 54
+#define RFC2132_PARAM_LIST 55
+#define RFC2132_MAX_SIZE 57
+#define RFC2132_VENDOR_CLASS_ID 60
+#define RFC2132_CLIENT_ID 61
+#define RFC2132_TFTP_SERVER_NAME 66
+#define RFC2132_BOOTFILE_NAME 67
+#define RFC3004_USER_CLASS 77
+
+#ifdef PXE_DHCP_STRICT
+/*
+ * The following options are acknowledged in RFC3679 because they are
+ * widely used by PXE implementations, but have never been properly
+ * allocated. Despite other PXE options being correctly packed in a
+ * vendor encapsulated field, these are exposed. Sigh. Note that the
+ * client UUID (option 97) is also noted in the PXE spec as using
+ * option 61.
+ */
+#define RFC3679_PXE_CLIENT_ARCH 93
+#define RFC3679_PXE_CLIENT_NDI 94
+#define RFC3679_PXE_CLIENT_UUID 97
+
+/* The lengths are fixed. */
+#define RFC3679_PXE_CLIENT_ARCH_LENGTH 2
+#define RFC3679_PXE_CLIENT_NDI_LENGTH 3
+#define RFC3679_PXE_CLIENT_UUID_LENGTH 17
+
+/*
+ * Values of RFC3679_PXE_CLIENT_ARCH can apparently be one of the
+ * following, according to the PXE spec. The spec only actually
+ * described the 2nd octet, not the first. Duh... assume 0.
+ */
+#define RFC3679_PXE_CLIENT_ARCH_IAX86PC 0,0
+#define RFC3679_PXE_CLIENT_ARCH_NECPC98 0,1
+#define RFC3679_PXE_CLIENT_ARCH_IA64PC 0,2
+#define RFC3679_PXE_CLIENT_ARCH_DECALPHA 0,3
+#define RFC3679_PXE_CLIENT_ARCH_ARCX86 0,4
+#define RFC3679_PXE_CLIENT_ARCH_INTELLEAN 0,5
+
+/*
+ * Only one valid value of NDI type (must be 1) and UNDI version (must
+ * be 2.1)
+ */
+#define RFC3679_PXE_CLIENT_NDI_21 1,2,1
+
+/*
+ * UUID - type must be 1 and then 16 octets of UID, as with the client ID.
+ * The value is a default for testing only
+ */
+#define RFC3679_PXE_CLIENT_UUID_TYPE 0
+#warning "UUID is a default for testing ONLY!"
+#define RFC3679_PXE_CLIENT_UUID_DEFAULT \
+ RFC3679_PXE_CLIENT_UUID_TYPE, \
+ 0xDE,0xAD,0xBE,0xEF, \
+ 0xDE,0xAD,0xBE,0xEF, \
+ 0xDE,0xAD,0xBE,0xEF, \
+ 0xDE,0xAD,0xBE,0xEF
+/*
+ * The Vendor Class ID. Note that the Arch and UNDI version numbers
+ * are fixed and must be same as the ARCH and NDI above.
+ */
+#define RFC2132_VENDOR_CLASS_ID_PXE_LENGTH 32
+#define RFC2132_VENDOR_CLASS_ID_PXE \
+ 'P','X','E','C','l','i','e','n','t',':', \
+ 'A','r','c','h',':','0','0','0','0','0',':', \
+ 'U','N','D','I',':','0','0','2','0','0','1'
+
+/*
+ * The following vendor options are required in the PXE spec to pull
+ * options for the *next* image. The PXE spec doesn't help us with
+ * this (like explaining why).
+ */
+#define RFC1533_VENDOR_PXE_OPT128 128
+#define RFC1533_VENDOR_PXE_OPT129 129
+#define RFC1533_VENDOR_PXE_OPT130 130
+#define RFC1533_VENDOR_PXE_OPT131 131
+#define RFC1533_VENDOR_PXE_OPT132 132
+#define RFC1533_VENDOR_PXE_OPT133 133
+#define RFC1533_VENDOR_PXE_OPT134 134
+#define RFC1533_VENDOR_PXE_OPT135 135
+
+#endif /* PXE_DHCP_STRICT */
+
+#define DHCPDISCOVER 1
+#define DHCPOFFER 2
+#define DHCPREQUEST 3
+#define DHCPACK 5
+#endif /* NO_DHCP_SUPPORT */
+
+#define RFC1533_VENDOR_MAJOR 0
+#define RFC1533_VENDOR_MINOR 0
+
+#define RFC1533_VENDOR_MAGIC 128
+#define RFC1533_VENDOR_ADDPARM 129
+#define RFC1533_VENDOR_ETHDEV 130
+/* We should really apply for an official Etherboot encap option */
+#define RFC1533_VENDOR_ETHERBOOT_ENCAP 150
+/* I'll leave it to FREEBSD to decide if they want to renumber */
+#ifdef IMAGE_FREEBSD
+#define RFC1533_VENDOR_HOWTO 132
+#define RFC1533_VENDOR_KERNEL_ENV 133
+#endif
+#define RFC1533_VENDOR_NIC_DEV_ID 175
+#define RFC1533_VENDOR_ARCH 177
+
+#define RFC1533_END 255
+
+#define BOOTP_VENDOR_LEN 64
+#ifndef NO_DHCP_SUPPORT
+#define DHCP_OPT_LEN 312
+#endif /* NO_DHCP_SUPPORT */
+
+/* Format of a bootp packet */
+struct bootp_t {
+ uint8_t bp_op;
+ uint8_t bp_htype;
+ uint8_t bp_hlen;
+ uint8_t bp_hops;
+ uint32_t bp_xid;
+ uint16_t bp_secs;
+ uint16_t unused;
+ in_addr bp_ciaddr;
+ in_addr bp_yiaddr;
+ in_addr bp_siaddr;
+ in_addr bp_giaddr;
+ uint8_t bp_hwaddr[16];
+ uint8_t bp_sname[64];
+ char bp_file[128];
+#ifdef NO_DHCP_SUPPORT
+ uint8_t bp_vend[BOOTP_VENDOR_LEN];
+#else
+ uint8_t bp_vend[DHCP_OPT_LEN];
+#endif /* NO_DHCP_SUPPORT */
+};
+
+/* Format of a bootp IP packet */
+struct bootpip_t
+{
+ struct iphdr ip;
+ struct udphdr udp;
+ struct bootp_t bp;
+};
+
+/* Format of bootp packet with extensions */
+struct bootpd_t {
+ struct bootp_t bootp_reply;
+ uint8_t bootp_extension[MAX_BOOTP_EXTLEN];
+};
+
+#endif /* _BOOTP_H */
diff --git a/gpxe/src/include/btext.h b/gpxe/src/include/btext.h
new file mode 100644
index 00000000..1d3f9e59
--- /dev/null
+++ b/gpxe/src/include/btext.h
@@ -0,0 +1,62 @@
+/*
+ * This file describes the structure passed from the BootX application
+ * (for MacOS) when it is used to boot Linux.
+ *
+ * Written by Benjamin Herrenschmidt.
+ *
+ * Move to LinuxBIOS by LYH yhlu@tyan.com
+ *
+ */
+
+
+#ifndef _BTEXT_H__
+#define _BTEXT_H__
+
+#if 1
+#define u32 unsigned int
+#define u16 unsigned short
+#define u8 unsigned char
+#endif
+
+/* Here are the boot informations that are passed to the bootstrap
+ * Note that the kernel arguments and the device tree are appended
+ * at the end of this structure. */
+typedef struct boot_infos
+{
+
+ /* NEW (vers. 2) this holds the current _logical_ base addr of
+ the frame buffer (for use by early boot message) */
+ u8* logicalDisplayBase;
+
+
+ /* Some infos about the current MacOS display */
+ u32 dispDeviceRect[4]; /* left,top,right,bottom */
+ u32 dispDeviceDepth; /* (8, 16 or 32) */
+ u32 dispDeviceBase; /* base address (physical) */
+ u32 dispDeviceRowBytes; /* rowbytes (in bytes) */
+ u32 dispDeviceColorsOffset; /* Colormap (8 bits only) or 0 (*) */
+
+
+ /* The framebuffer size (optional, currently 0) */
+ u32 frameBufferSize; /* Represents a max size, can be 0. */
+
+
+} boot_infos_t;
+
+/* (*) The format of the colormap is 256 * 3 * 2 bytes. Each color index is represented
+ * by 3 short words containing a 16 bits (unsigned) color component.
+ * Later versions may contain the gamma table for direct-color devices here.
+ */
+#define BOOTX_COLORTABLE_SIZE (256UL*3UL*2UL)
+
+
+/*
+ * Definitions for using the procedures in btext.c.
+ *
+ * Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ */
+
+extern boot_infos_t disp_bi;
+extern u32 boot_text_mapped;
+
+#endif /* _BTEXT_H */
diff --git a/gpxe/src/include/byteswap.h b/gpxe/src/include/byteswap.h
new file mode 100644
index 00000000..72b5a01d
--- /dev/null
+++ b/gpxe/src/include/byteswap.h
@@ -0,0 +1,22 @@
+#ifndef ETHERBOOT_BYTESWAP_H
+#define ETHERBOOT_BYTESWAP_H
+
+#include "endian.h"
+#include "bits/byteswap.h"
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#include "little_bswap.h"
+#endif
+#if __BYTE_ORDER == __BIG_ENDIAN
+#include "big_bswap.h"
+#endif
+
+/* Make routines available to all */
+#define swap64(x) __bswap_64(x)
+#define swap32(x) __bswap_32(x)
+#define swap16(x) __bswap_16(x)
+#define bswap_64(x) __bswap_64(x)
+#define bswap_32(x) __bswap_32(x)
+#define bswap_16(x) __bswap_16(x)
+
+#endif /* ETHERBOOT_BYTESWAP_H */
diff --git a/gpxe/src/include/cmdline.h b/gpxe/src/include/cmdline.h
new file mode 100644
index 00000000..9ab29c53
--- /dev/null
+++ b/gpxe/src/include/cmdline.h
@@ -0,0 +1,8 @@
+#ifndef CMDLINE_H
+#define CMDLINE_H
+
+/* Command line external functions */
+
+void cmdl_start();
+
+#endif
diff --git a/gpxe/src/include/cmdlinelib.h b/gpxe/src/include/cmdlinelib.h
new file mode 100644
index 00000000..1eb68994
--- /dev/null
+++ b/gpxe/src/include/cmdlinelib.h
@@ -0,0 +1,99 @@
+/* Command line library */
+#ifndef CMDLINELIB_H
+#define CMDLINELIB_H
+
+#define CMDL_BUFFER_SIZE 256
+//#define CMDL_OUTPUT_SIZE 256
+#define CMDL_PROMPT_SIZE 8
+#define CMDL_MAX_TAB_COMPLETE_RESULT 256
+
+typedef int (*cmdl_putchar_t)(int);
+typedef int (*cmdl_printf_t)( const char *format, ... );
+typedef int (*cmdl_getchar_t)();
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+enum{
+ CMDL_LEFT,
+ CMDL_RIGHT
+};
+
+enum{
+ CMDLK_FW=6,
+ CMDLK_BW=2,
+ CMDLK_BS=8,
+ CMDLK_HOME=2,
+ CMDLK_END=5,
+ CMDLK_DELTOEND=11,
+ CMDLK_DELARG=23,
+ CMDLK_ENTER=0x0d,
+ CMDLK_RETURN=0x0a,
+ CMDLK_TAB=9
+};
+
+typedef struct{
+
+ // buffers
+
+ //char* output;
+ char* buffer;
+ char* prompt;
+
+ // options and values
+
+ int cursor;
+ //int has_output;
+ int exit;
+ int refresh;
+ int tabstate;
+ int insert;
+
+ // callbacks
+
+ cmdl_putchar_t putchar;
+ cmdl_getchar_t getchar;
+ cmdl_printf_t printf;
+
+}cmd_line;
+
+typedef struct{
+ int argc;
+ char **argv;
+}cmdl_param_list;
+
+void cmdl_setputchar(cmd_line* cmd, cmdl_putchar_t in);
+void cmdl_setgetchar(cmd_line* cmd, cmdl_getchar_t in);
+void cmdl_setprintf(cmd_line* cmd, cmdl_printf_t in);
+
+//void cmdl_builtin_help(cmd_line* cmd, char* command);
+
+void cmdl_parsechar(cmd_line* cmd, char in);
+
+void cmdl_addreplace(cmd_line* cmd, char in);
+void cmdl_addinsert(cmd_line* cmd, char in);
+void cmdl_enterloop(cmd_line* cmd);
+void cmdl_exec(cmd_line* cmd);
+void cmdl_setexit(cmd_line* cmd, int exit);
+int cmdl_getexit(cmd_line* cmd);
+void cmdl_clearoutput(cmd_line* cmd);
+void cmdl_clearbuffer(cmd_line* cmd);
+int cmdl_printf(cmd_line* cmd, const char *format, ...);
+char* cmdl_getoutput(cmd_line* cmd);
+//void cmdl_addoutput_str(cmd_line* cmd, char output[CMDL_OUTPUT_SIZE]);
+void cmdl_addstr(cmd_line* cmd, char* str);
+int cmdl_movecursor(cmd_line* cmd, int direction);
+char* cmdl_getbuffer(cmd_line* cmd);
+void cmdl_addchar(cmd_line* cmd, char in);
+int cmdl_check(cmd_line* cmd);
+void cmdl_del(cmd_line* cmd);
+cmd_line* cmdl_create();
+void cmdl_free(cmd_line* cmd);
+char *cmdl_getprompt(cmd_line* cmd);
+void cmdl_setpropmt(cmd_line* cmd, char prompt[CMDL_PROMPT_SIZE]);
+cmdl_param_list* cmdl_getparams(const char* command);
+void cmdl_tabcomplete(cmd_line *cmd);
+
+#endif
+
diff --git a/gpxe/src/include/cmdlist.h b/gpxe/src/include/cmdlist.h
new file mode 100644
index 00000000..33cd349b
--- /dev/null
+++ b/gpxe/src/include/cmdlist.h
@@ -0,0 +1,18 @@
+#ifndef COMMANDLIST_H
+#define COMMANDLIST_H
+
+void test_req();
+void test2_req();
+void help_req();
+void nvo_cmd_req();
+
+void commandlist()
+{
+ // test_req();
+ // test2_req();
+ help_req();
+ nvo_cmd_req();
+}
+
+#endif
+
diff --git a/gpxe/src/include/coff.h b/gpxe/src/include/coff.h
new file mode 100644
index 00000000..a73fda52
--- /dev/null
+++ b/gpxe/src/include/coff.h
@@ -0,0 +1,73 @@
+#ifndef COFF_H
+#define COFF_H
+/* Based on the elf.h file
+ * Changed accordingly to support COFF file support
+ */
+
+
+/* Values for f_flags. */
+#define F_RELFLG 0x0001 /* If set, not reloc. info. Clear for executables */
+#define F_EXEC 0x0002 /* No unresolved symbols. Executable file ! */
+#define F_LNNO 0x0004 /* If set, line information numbers removed */
+#define F_LSYMS 0x0008 /* If set, local symbols removed */
+#define F_AR32WR 0x0100 /* Indicates little endian file */
+
+/* Values for e_machine (architecute). */
+#define EM_E1 0x17a /* Magic number for Hyperstone. Big endian format */
+
+/* Values for f_flags. */
+#define O_MAGIC 0x017c /* Optional's header magic number for Hyperstone */
+
+/* Values for s_flags. */
+#define S_TYPE_TEXT 0x0020 /* If set, the section contains only executable */
+#define S_TYPE_DATA 0x0040 /* If set, the section contains only initialized data */
+#define S_TYPE_BSS 0x0080 /* If set, the section is BSS no data stored */
+
+
+typedef struct
+{
+ unsigned short f_magic; /* magic number */
+ unsigned short f_nscns; /* number of sections */
+ unsigned long f_timdat; /* time & date stamp */
+ unsigned long f_symptr; /* file pointer to symtab */
+ unsigned long f_nsyms; /* number of symtab entries */
+ unsigned short f_opthdr; /* sizeof(optional hdr) */
+ unsigned short f_flags; /* flags */
+}
+COFF_filehdr;
+
+/*
+ * Optional header.
+ */
+typedef struct
+{
+ unsigned short magic; /* type of file */
+ unsigned short vstamp; /* version stamp */
+ unsigned long tsize; /* text size in bytes, padded to FW bdry*/
+ unsigned long dsize; /* initialized data " " */
+ unsigned long bsize; /* uninitialized data " " */
+ unsigned long entry; /* entry pt. */
+ unsigned long text_start; /* base of text used for this file */
+ unsigned long data_start; /* base of data used for this file */
+}
+COFF_opthdr;
+
+/*
+ * Section header.
+ */
+typedef struct
+{
+ char s_name[8]; /* section name */
+ unsigned long s_paddr; /* physical address, aliased s_nlib */
+ unsigned long s_vaddr; /* virtual address */
+ unsigned long s_size; /* section size */
+ unsigned long s_scnptr; /* file ptr to raw data for section */
+ unsigned long s_relptr; /* file ptr to relocation */
+ unsigned long s_lnnoptr; /* file ptr to line numbers */
+ unsigned short s_nreloc; /* number of relocation entries */
+ unsigned short s_nlnno; /* number of line number entries*/
+ unsigned long s_flags; /* flags */
+}
+COFF_scnhdr;
+
+#endif /* COFF_H */
diff --git a/gpxe/src/include/compiler.h b/gpxe/src/include/compiler.h
new file mode 100644
index 00000000..1d4312a6
--- /dev/null
+++ b/gpxe/src/include/compiler.h
@@ -0,0 +1,357 @@
+#ifndef COMPILER_H
+#define COMPILER_H
+
+/*
+ * Doxygen can't cope with some of the more esoteric areas of C, so we
+ * make its life simpler.
+ *
+ */
+#ifdef DOXYGEN
+#define __attribute__(x)
+#endif
+
+/** @file
+ *
+ * Global compiler definitions.
+ *
+ * This file is implicitly included by every @c .c file in Etherboot.
+ * It defines global macros such as DBG().
+ *
+ * We arrange for each object to export the symbol @c obj_OBJECT
+ * (where @c OBJECT is the object name, e.g. @c rtl8139) as a global
+ * symbol, so that the linker can drag in selected object files from
+ * the library using <tt> -u obj_OBJECT </tt>.
+ *
+ */
+
+/* Not quite sure why cpp requires two levels of macro call in order
+ * to actually expand OBJECT...
+ */
+#undef _H1
+#define _H1( x, y ) x ## y
+#undef _H2
+#define _H2( x, y ) _H1 ( x, y )
+#define PREFIX_OBJECT(prefix) _H2 ( prefix, OBJECT )
+#define OBJECT_SYMBOL PREFIX_OBJECT(obj_)
+#undef _STR
+#define _STR(s) #s
+#undef _XSTR
+#define _XSTR(s) _STR(s)
+#define OBJECT_SYMBOL_STR _XSTR ( OBJECT_SYMBOL )
+
+#ifdef ASSEMBLY
+
+ .globl OBJECT_SYMBOL
+ .equ OBJECT_SYMBOL, 0
+
+#else /* ASSEMBLY */
+
+__asm__ ( ".globl\t" OBJECT_SYMBOL_STR );
+__asm__ ( ".equ\t" OBJECT_SYMBOL_STR ", 0" );
+
+/**
+ * Drag in an object by object name.
+ *
+ * Macro to allow objects to explicitly drag in other objects by
+ * object name. Used by config.c.
+ *
+ */
+#define REQUIRE_OBJECT(object) \
+ __asm__ ( ".equ\tneed_" #object ", obj_" #object );
+
+/** @def DBG
+ *
+ * Print a debugging message.
+ *
+ * The debug level is set at build time by specifying the @c DEBUG=
+ * parameter on the @c make command line. For example, to enable
+ * debugging for the PCI bus functions (in pci.c) in a @c .dsk image
+ * for the @c rtl8139 card, you could use the command line
+ *
+ * @code
+ *
+ * make bin/rtl8139.dsk DEBUG=pci
+ *
+ * @endcode
+ *
+ * This will enable the debugging statements (DBG()) in pci.c. If
+ * debugging is not enabled, DBG() statements will be ignored.
+ *
+ * You can enable debugging in several objects simultaneously by
+ * separating them with commas, as in
+ *
+ * @code
+ *
+ * make bin/rtl8139.dsk DEBUG=pci,buffer,heap
+ *
+ * @endcode
+ *
+ * You can increase the debugging level for an object by specifying it
+ * with @c :N, where @c N is the level, as in
+ *
+ * @code
+ *
+ * make bin/rtl8139.dsk DEBUG=pci,buffer:2,heap
+ *
+ * @endcode
+ *
+ * which would enable debugging for the PCI, buffer-handling and
+ * heap-allocation code, with the buffer-handling code at level 2.
+ *
+ */
+
+/*
+ * If debug_OBJECT is set to a true value, the macro DBG(...) will
+ * expand to printf(...) when compiling OBJECT, and the symbol
+ * DEBUG_LEVEL will be inserted into the object file.
+ *
+ */
+#define DEBUG_SYMBOL PREFIX_OBJECT(debug_)
+
+#if DEBUG_SYMBOL
+#define DEBUG_SYMBOL_STR _XSTR ( DEBUG_SYMBOL )
+__asm__ ( ".equ\tDBGLVL, " DEBUG_SYMBOL_STR );
+#endif
+
+/** printf() for debugging
+ *
+ * This function exists so that the DBG() macros can expand to
+ * printf() calls without dragging the printf() prototype into scope.
+ *
+ * As far as the compiler is concerned, dbg_printf() and printf() are
+ * completely unrelated calls; it's only at the assembly stage that
+ * references to the dbg_printf symbol are collapsed into references
+ * to the printf symbol.
+ */
+extern int __attribute__ (( format ( printf, 1, 2 ) ))
+dbg_printf ( const char *fmt, ... ) asm ( "printf" );
+
+extern void dbg_autocolourise ( unsigned long id );
+extern void dbg_decolourise ( void );
+extern void dbg_hex_dump_da ( unsigned long dispaddr,
+ const void *data, unsigned long len );
+
+/* Compatibility with existing Makefile */
+#if DEBUG_SYMBOL
+#define DBGLVL DEBUG_SYMBOL
+#else
+#define DBGLVL 0
+#endif
+
+#define DBGLVL_LOG 1
+#define DBG_LOG ( DBGLVL & DBGLVL_LOG )
+#define DBGLVL_EXTRA 2
+#define DBG_EXTRA ( DBGLVL & DBGLVL_EXTRA )
+#define DBGLVL_PROFILE 4
+#define DBG_PROFILE ( DBGLVL & DBGLVL_PROFILE )
+#define DBGLVL_IO 8
+#define DBG_IO ( DBGLVL & DBGLVL_IO )
+
+/**
+ * Print debugging message if we are at a certain debug level
+ *
+ * @v level Debug level
+ * @v ... printf() argument list
+ */
+#define DBG_IF( level, ... ) do { \
+ if ( DBG_ ## level ) { \
+ dbg_printf ( __VA_ARGS__ ); \
+ } \
+ } while ( 0 )
+
+/**
+ * Print a hex dump if we are at a certain debug level
+ *
+ * @v level Debug level
+ * @v dispaddr Display address
+ * @v data Data to print
+ * @v len Length of data
+ */
+#define DBG_HDA_IF( level, dispaddr, data, len ) do { \
+ if ( DBG_ ## level ) { \
+ union { \
+ unsigned long ul; \
+ typeof ( dispaddr ) raw; \
+ } da; \
+ da.raw = dispaddr; \
+ dbg_hex_dump_da ( da.ul, data, len ); \
+ } \
+ } while ( 0 )
+
+/**
+ * Print a hex dump if we are at a certain debug level
+ *
+ * @v level Debug level
+ * @v data Data to print
+ * @v len Length of data
+ */
+#define DBG_HD_IF( level, data, len ) do { \
+ DBG_HDA_IF ( level, data, data, len ); \
+ } while ( 0 )
+
+/**
+ * Select colour for debug messages if we are at a certain debug level
+ *
+ * @v level Debug level
+ * @v id Message stream ID
+ */
+#define DBG_AC_IF( level, id ) do { \
+ if ( DBG_ ## level ) { \
+ union { \
+ unsigned long ul; \
+ typeof ( id ) raw; \
+ } dbg_stream; \
+ dbg_stream.raw = id; \
+ dbg_autocolourise ( dbg_stream.ul ); \
+ } \
+ } while ( 0 )
+
+/**
+ * Revert colour for debug messages if we are at a certain debug level
+ *
+ * @v level Debug level
+ */
+#define DBG_DC_IF( level ) do { \
+ if ( DBG_ ## level ) { \
+ dbg_decolourise(); \
+ } \
+ } while ( 0 )
+
+/* Autocolourising versions of the DBGxxx_IF() macros */
+
+#define DBGC_IF( level, id, ... ) do { \
+ DBG_AC_IF ( level, id ); \
+ DBG_IF ( level, __VA_ARGS__ ); \
+ DBG_DC_IF ( level ); \
+ } while ( 0 )
+
+#define DBGC_HDA_IF( level, id, ... ) do { \
+ DBG_AC_IF ( level, id ); \
+ DBG_HDA_IF ( level, __VA_ARGS__ ); \
+ DBG_DC_IF ( level ); \
+ } while ( 0 )
+
+#define DBGC_HD_IF( level, id, ... ) do { \
+ DBG_AC_IF ( level, id ); \
+ DBG_HD_IF ( level, __VA_ARGS__ ); \
+ DBG_DC_IF ( level ); \
+ } while ( 0 )
+
+/* Versions of the DBGxxx_IF() macros that imply DBGxxx_IF( LOG, ... )*/
+
+#define DBG( ... ) DBG_IF ( LOG, __VA_ARGS__ )
+#define DBG_HDA( ... ) DBG_HDA_IF ( LOG, __VA_ARGS__ )
+#define DBG_HD( ... ) DBG_HD_IF ( LOG, __VA_ARGS__ )
+#define DBGC( ... ) DBGC_IF ( LOG, __VA_ARGS__ )
+#define DBGC_HDA( ... ) DBGC_HDA_IF ( LOG, __VA_ARGS__ )
+#define DBGC_HD( ... ) DBGC_HD_IF ( LOG, __VA_ARGS__ )
+
+/* Versions of the DBGxxx_IF() macros that imply DBGxxx_IF( EXTRA, ... )*/
+
+#define DBG2( ... ) DBG_IF ( EXTRA, __VA_ARGS__ )
+#define DBG2_HDA( ... ) DBG_HDA_IF ( EXTRA, __VA_ARGS__ )
+#define DBG2_HD( ... ) DBG_HD_IF ( EXTRA, __VA_ARGS__ )
+#define DBGC2( ... ) DBGC_IF ( EXTRA, __VA_ARGS__ )
+#define DBGC2_HDA( ... ) DBGC_HDA_IF ( EXTRA, __VA_ARGS__ )
+#define DBGC2_HD( ... ) DBGC_HD_IF ( EXTRA, __VA_ARGS__ )
+
+/* Versions of the DBGxxx_IF() macros that imply DBGxxx_IF( PROFILE, ... )*/
+
+#define DBGP( ... ) DBG_IF ( PROFILE, __VA_ARGS__ )
+#define DBGP_HDA( ... ) DBG_HDA_IF ( PROFILE, __VA_ARGS__ )
+#define DBGP_HD( ... ) DBG_HD_IF ( PROFILE, __VA_ARGS__ )
+#define DBGCP( ... ) DBGC_IF ( PROFILE, __VA_ARGS__ )
+#define DBGCP_HDA( ... ) DBGC_HDA_IF ( PROFILE, __VA_ARGS__ )
+#define DBGCP_HD( ... ) DBGC_HD_IF ( PROFILE, __VA_ARGS__ )
+
+/* Versions of the DBGxxx_IF() macros that imply DBGxxx_IF( IO, ... )*/
+
+#define DBGIO( ... ) DBG_IF ( IO, __VA_ARGS__ )
+#define DBGIO_HDA( ... ) DBG_HDA_IF ( IO, __VA_ARGS__ )
+#define DBGIO_HD( ... ) DBG_HD_IF ( IO, __VA_ARGS__ )
+#define DBGCIO( ... ) DBGC_IF ( IO, __VA_ARGS__ )
+#define DBGCIO_HDA( ... ) DBGC_HDA_IF ( IO, __VA_ARGS__ )
+#define DBGCIO_HD( ... ) DBGC_HD_IF ( IO, __VA_ARGS__ )
+
+
+#if DEBUG_SYMBOL == 0
+#define NDEBUG
+#endif
+
+/** Select file identifier for errno.h (if used) */
+#define ERRFILE PREFIX_OBJECT ( ERRFILE_ )
+
+/** Declare a data structure as packed. */
+#define PACKED __attribute__ (( packed ))
+
+/** Declare a variable or data structure as unused. */
+#define __unused __attribute__ (( unused ))
+
+/** Apply standard C calling conventions */
+#define __cdecl __attribute__ (( cdecl , regparm(0) ))
+
+/**
+ * Declare a function as pure - i.e. without side effects
+ */
+#define __pure __attribute__ (( pure ))
+
+/**
+ * Declare a function as const - i.e. it does not access global memory
+ * (including dereferencing pointers passed to it) at all.
+ * Must also not call any non-const functions.
+ */
+#define __const __attribute__ (( const ))
+
+/**
+ * Declare a function's pointer parameters as non-null - i.e. force
+ * compiler to check pointers at compile time and enable possible
+ * optimizations based on that fact
+ */
+#define __nonnull __attribute__ (( nonnull ))
+
+/**
+ * Declare a pointer returned by a function as a unique memory address
+ * as returned by malloc-type functions.
+ */
+#define __malloc __attribute__ (( malloc ))
+
+/**
+ * Declare a function as used.
+ *
+ * Necessary only if the function is called only from assembler code.
+ */
+#define __used __attribute__ (( used ))
+
+/** Declare a data structure to be aligned with 16-byte alignment */
+#define __aligned __attribute__ (( aligned ( 16 ) ))
+
+/**
+ * Shared data.
+ *
+ * To save space in the binary when multiple-driver images are
+ * compiled, uninitialised data areas can be shared between drivers.
+ * This will typically be used to share statically-allocated receive
+ * and transmit buffers between drivers.
+ *
+ * Use as e.g.
+ *
+ * @code
+ *
+ * struct {
+ * char rx_buf[NUM_RX_BUF][RX_BUF_SIZE];
+ * char tx_buf[TX_BUF_SIZE];
+ * } my_static_data __shared;
+ *
+ * @endcode
+ *
+ */
+#define __shared __asm__ ( "_shared_bss" )
+
+/**
+ * Optimisation barrier
+ */
+#define barrier() __asm__ __volatile__ ( "" : : : "memory" )
+
+#endif /* ASSEMBLY */
+
+#endif /* COMPILER_H */
diff --git a/gpxe/src/include/console.h b/gpxe/src/include/console.h
new file mode 100644
index 00000000..9addd526
--- /dev/null
+++ b/gpxe/src/include/console.h
@@ -0,0 +1,114 @@
+#ifndef CONSOLE_H
+#define CONSOLE_H
+
+#include <gpxe/tables.h>
+
+/** @file
+ *
+ * User interaction.
+ *
+ * Various console devices can be selected via the build options
+ * CONSOLE_FIRMWARE, CONSOLE_SERIAL etc. The console functions
+ * putchar(), getchar() and iskey() delegate to the individual console
+ * drivers.
+ *
+ */
+
+/**
+ * A console driver
+ *
+ * Defines the functions that implement a particular console type.
+ * Must be made part of the console drivers table by using
+ * #__console_driver.
+ *
+ * @note Consoles that cannot be used before their initialisation
+ * function has completed should set #disabled=1 initially. This
+ * allows other console devices to still be used to print out early
+ * debugging messages.
+ *
+ */
+struct console_driver {
+ /** Console is disabled.
+ *
+ * The console's putchar(), putline(), getchar() and iskey()
+ * methods will not be called while #disabled==1. Typically
+ * the console's initialisation functions will set #disabled=0
+ * upon completion.
+ *
+ */
+ int disabled;
+
+ /** Write a character to the console.
+ *
+ * @v character Character to be written
+ * @ret None -
+ * @err None -
+ *
+ */
+ void ( *putchar ) ( int character );
+
+ /** Write an entire line to the console.
+ * This is intended to be used by line-oriented output media,
+ * like system logging facilities or line printers.
+ * Line output will not contain non-printable characters.
+ *
+ * @v linebuffer Pointer to the \0-terminated line
+ * @ret None -
+ * @err None -
+ */
+ void ( * putline ) ( unsigned char * linebuffer );
+
+ /** Read a character from the console.
+ *
+ * @v None -
+ * @ret character Character read
+ * @err None -
+ *
+ * If no character is available to be read, this method will
+ * block. The character read should not be echoed back to the
+ * console.
+ *
+ */
+ int ( *getchar ) ( void );
+
+ /** Check for available input.
+ *
+ * @v None -
+ * @ret True Input is available
+ * @ret False Input is not available
+ * @err None -
+ *
+ * This should return True if a subsequent call to getchar()
+ * will not block.
+ *
+ */
+ int ( *iskey ) ( void );
+};
+
+/**
+ * Mark a <tt> struct console_driver </tt> as being part of the
+ * console drivers table.
+ *
+ * Use as e.g.
+ *
+ * @code
+ *
+ * struct console_driver my_console __console_driver = {
+ * .putchar = my_putchar,
+ * .getchar = my_getchar,
+ * .iskey = my_iskey,
+ * };
+ *
+ * @endcode
+ *
+ */
+#define __console_driver __table ( struct console_driver, console, 01 )
+
+/* Function prototypes */
+
+extern void putchar ( int character );
+extern int getchar ( void );
+extern int iskey ( void );
+extern int getkey ( void );
+
+#endif /* CONSOLE_H */
diff --git a/gpxe/src/include/cpu.h b/gpxe/src/include/cpu.h
new file mode 100644
index 00000000..b2c428f7
--- /dev/null
+++ b/gpxe/src/include/cpu.h
@@ -0,0 +1,6 @@
+#ifndef CPU_H
+#define CPU_H
+
+#include "bits/cpu.h"
+
+#endif /* CPU_H */
diff --git a/gpxe/src/include/ctype.h b/gpxe/src/include/ctype.h
new file mode 100644
index 00000000..a79395d2
--- /dev/null
+++ b/gpxe/src/include/ctype.h
@@ -0,0 +1,28 @@
+#ifndef _CTYPE_H
+#define _CTYPE_H
+
+/** @file
+ *
+ * Character types
+ */
+
+#define isdigit(c) ((c & 0x04) != 0)
+#define islower(c) ((c & 0x02) != 0)
+//#define isspace(c) ((c & 0x20) != 0)
+#define isupper(c) ((c & 0x01) != 0)
+
+static inline unsigned char tolower(unsigned char c)
+{
+ if (isupper(c))
+ c -= 'A'-'a';
+ return c;
+}
+
+static inline unsigned char toupper(unsigned char c)
+{
+ if (islower(c))
+ c -= 'a'-'A';
+ return c;
+}
+
+#endif /* _CTYPE_H */
diff --git a/gpxe/src/include/curses.h b/gpxe/src/include/curses.h
new file mode 100644
index 00000000..6b1c42d8
--- /dev/null
+++ b/gpxe/src/include/curses.h
@@ -0,0 +1,753 @@
+#ifndef CURSES_H
+#define CURSES_H
+
+#include <stdint.h>
+#include <stdarg.h>
+
+/** @file
+ *
+ * MuCurses header file
+ *
+ */
+
+#undef ERR
+#define ERR (-1)
+
+#undef FALSE
+#define FALSE (0)
+
+#undef OK
+#define OK (0)
+
+#undef TRUE
+#define TRUE (1)
+
+typedef int bool;
+typedef uint32_t chtype;
+typedef uint32_t attr_t;
+
+/** Curses SCREEN object */
+typedef struct _curses_screen {
+ /** Current cursor position */
+ unsigned int curs_x, curs_y;
+ /** Current attribute */
+ attr_t attrs;
+
+ void ( *init ) ( struct _curses_screen *scr );
+ void ( *exit ) ( struct _curses_screen *scr );
+ /**
+ * Move cursor to position specified by x,y coords
+ *
+ * @v scr screen on which to operate
+ * @v y Y position
+ * @v x X position
+ */
+ void ( * movetoyx ) ( struct _curses_screen *scr,
+ unsigned int y, unsigned int x );
+ /**
+ * Write character to current cursor position
+ *
+ * @v scr screen on which to operate
+ * @v c character to be written
+ */
+ void ( * putc ) ( struct _curses_screen *scr, chtype c );
+ /**
+ * Pop a character from the keyboard input stream
+ *
+ * @v scr screen on which to operate
+ * @ret c popped character
+ */
+ int ( * getc ) ( struct _curses_screen *scr );
+ /**
+ * Checks to see whether a character is waiting in the input stream
+ *
+ * @v scr screen on which to operate
+ * @ret TRUE character waiting in stream
+ * @ret FALSE no character waiting in stream
+ */
+ bool ( *peek ) ( struct _curses_screen *scr );
+} SCREEN;
+
+/** Curses Window struct */
+typedef struct _curses_window {
+ /** screen with which window associates */
+ SCREEN *scr;
+ /** window attributes */
+ attr_t attrs;
+ /** window origin coordinates */
+ unsigned int ori_x, ori_y;
+ /** window cursor position */
+ unsigned int curs_x, curs_y;
+ /** window dimensions */
+ unsigned int width, height;
+ /** parent window */
+ struct _curses_window *parent;
+ /** windows that share the same parent as this one */
+ //struct list_head siblings;
+ /** windows der'd or sub'd from this one */
+ //struct list_head children;
+} WINDOW;
+
+extern WINDOW _stdscr;
+extern unsigned short _COLS;
+extern unsigned short _LINES;
+
+#define stdscr ( &_stdscr )
+#define COLS _COLS
+#define LINES _LINES
+
+#define MUCURSES_BITS( mask, shift ) (( mask ) << (shift))
+#define CPAIR_SHIFT 8
+#define ATTRS_SHIFT 16
+
+#define WA_DEFAULT ( 0x0000 << ATTRS_SHIFT )
+#define WA_ALTCHARSET ( 0x0001 << ATTRS_SHIFT )
+#define WA_BLINK ( 0x0002 << ATTRS_SHIFT )
+#define WA_BOLD ( 0x0004 << ATTRS_SHIFT )
+#define WA_DIM ( 0x0008 << ATTRS_SHIFT )
+#define WA_INVIS ( 0x0010 << ATTRS_SHIFT )
+#define WA_PROTECT ( 0x0020 << ATTRS_SHIFT )
+#define WA_REVERSE ( 0x0040 << ATTRS_SHIFT )
+#define WA_STANDOUT ( 0x0080 << ATTRS_SHIFT )
+#define WA_UNDERLINE ( 0x0100 << ATTRS_SHIFT )
+#define WA_HORIZONTAL ( 0x0200 << ATTRS_SHIFT )
+#define WA_VERTICAL ( 0x0400 << ATTRS_SHIFT )
+#define WA_LEFT ( 0x0800 << ATTRS_SHIFT )
+#define WA_RIGHT ( 0x1000 << ATTRS_SHIFT )
+#define WA_LOW ( 0x2000 << ATTRS_SHIFT )
+#define WA_TOP ( 0x4000 << ATTRS_SHIFT )
+
+#define A_DEFAULT WA_DEFAULT
+#define A_ALTCHARSET WA_ALTCHARSET
+#define A_BLINK WA_BLINK
+#define A_BOLD WA_BOLD
+#define A_DIM WA_DIM
+#define A_INVIS WA_INVIS
+#define A_PROTECT WA_PROTECT
+#define A_REVERSE WA_REVERSE
+#define A_STANDOUT WA_STANDOUT
+#define A_UNDERLINE WA_UNDERLINE
+
+#define A_ATTRIBUTES ( 0xffff << ATTRS_SHIFT )
+#define A_CHARTEXT ( 0xff )
+#define A_COLOUR ( 0xff << CPAIR_SHIFT )
+#define A_COLOR A_COLOUR
+
+#define COLOUR_PAIR(n) ( (n) << CPAIR_SHIFT )
+#define COLOR_PAIR(n) COLOUR_PAIR(n)
+#define PAIR_NUMBER(attrs) ( ( (attrs) & A_COLOUR ) >> CPAIR_SHIFT )
+
+#define COLOUR_PAIRS 8 /* Arbitrary limit */
+#define COLOR_PAIRS COLOUR_PAIRS
+
+#define ACS_ULCORNER '+'
+#define ACS_LLCORNER '+'
+#define ACS_URCORNER '+'
+#define ACS_LRCORNER '+'
+#define ACS_RTEE '+'
+#define ACS_LTEE '+'
+#define ACS_BTEE '+'
+#define ACS_TTEE '+'
+#define ACS_HLINE '-'
+#define ACS_VLINE '|'
+#define ACS_PLUS '+'
+#define ACS_S1 '-'
+#define ACS_S9 '_'
+#define ACS_DIAMOND '+'
+#define ACS_CKBOARD ':'
+#define ACS_DEGREE '\''
+#define ACS_PLMINUS '#'
+#define ACS_BULLET 'o'
+#define ACS_LARROW '<'
+#define ACS_RARROW '>'
+#define ACS_DARROW 'v'
+#define ACS_UARROW '^'
+#define ACS_BOARD '#'
+#define ACS_LANTERN '#'
+#define ACS_BLOCK '#'
+
+#define COLOUR_BLACK 0
+#define COLOUR_RED 1
+#define COLOUR_GREEN 2
+#define COLOUR_YELLOW 3
+#define COLOUR_BLUE 4
+#define COLOUR_MAGENTA 5
+#define COLOUR_CYAN 6
+#define COLOUR_WHITE 7
+#define COLOURS 7
+
+#define COLOUR_FG 30
+#define COLOUR_BG 40
+#define COLOR_FG COLOUR_FG
+#define COLOR_BG COLOUR_BG
+
+#define COLOR_BLACK COLOUR_BLACK
+#define COLOR_BLUE COLOUR_BLUE
+#define COLOR_GREEN COLOUR_GREEN
+#define COLOR_CYAN COLOUR_CYAN
+#define COLOR_RED COLOUR_RED
+#define COLOR_MAGENTA COLOUR_MAGENTA
+#define COLOR_YELLOW COLOUR_YELLOW
+#define COLOR_WHITE COLOUR_WHITE
+#define COLORS COLOURS
+
+/*
+ * KEY code constants are define in gpxe/keys.h
+ */
+#include <gpxe/keys.h>
+
+//extern int addch ( const chtype * );
+//extern int addchnstr ( const chtype *, int );
+//extern int addchstr ( const chtype * );
+//extern int addnstr ( const char *, int );
+//extern int addstr ( const char * );
+//extern int attroff ( int );
+//extern int attron ( int );
+//extern int attrset ( int );
+//extern int attr_get ( attr_t *, short *, void * );
+//extern int attr_off ( attr_t, void * );
+//extern int attr_on ( attr_t, void * );
+//extern int attr_set ( attr_t, short, void * );
+extern int baudrate ( void );
+extern int beep ( void );
+//extern void bkgdset ( chtype );
+/*extern int border ( chtype, chtype, chtype, chtype, chtype, chtype, chtype,
+ chtype );*/
+extern int box ( WINDOW *, chtype, chtype ) __nonnull;
+//extern bool can_change_colour ( void );
+#define can_change_color() can_change_colour()
+extern int cbreak ( void );
+//extern int clrtobot ( void );
+//extern int clrtoeol ( void );
+extern int colour_content ( short, short *, short *, short * ) __nonnull;
+#define color_content( c, r, g, b ) colour_content( (c), (r), (g), (b) )
+//extern int colour_set ( short, void * );
+#define color_set( cpno, opts ) colour_set( (cpno), (opts) )
+extern int copywin ( const WINDOW *, WINDOW *, int, int, int,
+ int, int, int, int );
+extern int curs_set ( int );
+extern int def_prog_mode ( void );
+extern int def_shell_mode ( void );
+extern int delay_output ( int );
+//extern int delch ( void );
+//extern int deleteln ( void );
+extern void delscreen ( SCREEN * );
+extern int delwin ( WINDOW * ) __nonnull;
+extern WINDOW *derwin ( WINDOW *, int, int, int, int ) __nonnull;
+//extern int doupdate ( void );
+extern WINDOW *dupwin ( WINDOW * ) __nonnull;
+extern int echo ( void );
+extern int echochar ( const chtype );
+extern int endwin ( void );
+extern char erasechar ( void );
+//extern int erase ( void );
+extern void filter ( void );
+extern int flash ( void );
+extern int flushinp ( void );
+extern __pure chtype getbkgd ( WINDOW * ) __nonnull;
+//extern int getch ( void );
+//extern int getnstr ( char *, int );
+//extern int getstr ( char * );
+extern int halfdelay ( int );
+//extern bool has_colors ( void );
+extern bool has_ic ( void );
+extern bool has_il ( void );
+//extern int hline ( chtype, int );
+extern void idcok ( WINDOW *, bool );
+extern int idlok ( WINDOW *, bool );
+//extern void immedok ( WINDOW *, bool );
+//extern chtype inch ( void );
+//extern int inchnstr ( chtype *, int );
+//extern int inchstr ( chtype * );
+extern WINDOW *initscr ( void );
+extern int init_colour ( short, short, short, short );
+#define init_color ( c, r, g, b ) init_colour ( (c), (r), (g), (b) )
+extern int init_pair ( short, short, short );
+//extern int innstr ( char *, int );
+//extern int insch ( chtype );
+//extern int insnstr ( const char *, int );
+//extern int insstr ( const char * );
+//extern int instr ( char * );
+extern int intrflush ( WINDOW *, bool );
+extern bool isendwin ( void );
+//extern bool is_linetouched ( WINDOW *, int );
+//extern bool is_wintouched ( WINDOW * );
+extern char *keyname ( int );
+extern int keypad ( WINDOW *, bool );
+extern char killchar ( void );
+extern int leaveok ( WINDOW *, bool );
+extern char *longname ( void );
+extern int meta ( WINDOW *, bool );
+//extern int move ( int, int );
+//extern int mvaddch ( int, int, const chtype );
+//extern int mvaddchnstr ( int, int, const chtype *, int );
+//extern int mvaddchstr ( int, int, const chtype * );
+//extern int mvaddnstr ( int, int, const char *, int );
+//extern int mvaddstr ( int, int, const char * );
+extern int mvcur ( int, int, int, int );
+//extern int mvdelch ( int, int );
+extern int mvderwin ( WINDOW *, int, int );
+//extern int mvgetch ( int, int );
+//extern int mvgetnstr ( int, int, char *, int );
+//extern int mvgetstr ( int, int, char * );
+//extern int mvhline ( int, int, chtype, int );
+//extern chtype mvinch ( int, int );
+//extern int mvinchnstr ( int, int, chtype *, int );
+//extern int mvinchstr ( int, int, chtype * );
+//extern int mvinnstr ( int, int, char *, int );
+//extern int mvinsch ( int, int, chtype );
+//extern int mvinsnstr ( int, int, const char *, int );
+//extern int mvinsstr ( int, int, const char * );
+//extern int mvinstr ( int, int, char * );
+//extern int mvprintw ( int, int, char *, ... );
+//extern int mvscanw ( int, int, char *, ... );
+//extern int mvvline ( int, int, chtype, int );
+//extern int mvwaddch ( WINDOW *, int, int, const chtype );
+//extern int mvwaddchnstr ( WINDOW *, int, int, const chtype *, int );
+//extern int mvwaddchstr ( WINDOW *, int, int, const chtype * );
+//extern int mvwaddnstr ( WINDOW *, int, int, const char *, int );
+//extern int mvwaddstr ( WINDOW *, int, int, const char * );
+//extern int mvwdelch ( WINDOW *, int, int );
+//extern int mvwgetch ( WINDOW *, int, int );
+//extern int mvwgetnstr ( WINDOW *, int, int, char *, int );
+//extern int mvwgetstr ( WINDOW *, int, int, char * );
+//extern int mvwhline ( WINDOW *, int, int, chtype, int );
+extern int mvwin ( WINDOW *, int, int ) __nonnull;
+//extern chtype mvwinch ( WINDOW *, int, int );
+//extern int mvwinchnstr ( WINDOW *, int, int, chtype *, int );
+//extern int mvwinchstr ( WINDOW *, int, int, chtype * );
+//extern int mvwinnstr ( WINDOW *, int, int, char *, int );
+//extern int mvwinsch ( WINDOW *, int, int, chtype );
+//extern int mvwinsnstr ( WINDOW *, int, int, const char *, int );
+//extern int mvwinsstr ( WINDOW *, int, int, const char * );
+//extern int mvwinstr ( WINDOW *, int, int, char * );
+//extern int mvwprintw ( WINDOW *, int, int, char *, ... );
+//extern int mvwscanw ( WINDOW *, int, int, char *, ... );
+//extern int mvwvline ( WINDOW *, int, int, chtype, int );
+extern int napms ( int );
+//extern WINDOW *newpad ( int, int );
+extern WINDOW *newwin ( int, int, int, int );
+extern int nl ( void );
+extern int nocbreak ( void );
+extern int nodelay ( WINDOW *, bool );
+extern int noecho ( void );
+extern int nonl ( void );
+extern void noqiflush ( void );
+extern int noraw ( void );
+extern int notimeout ( WINDOW *, bool );
+extern int overlay ( const WINDOW *, WINDOW * );
+extern int overwrite ( const WINDOW *, WINDOW * );
+extern int pair_content ( short, short *, short * ) __nonnull;
+//extern int pechochar ( WINDOW *, chtype );
+//extern int pnoutrefresh ( WINDOW *, int, int, int, int, int, int );
+//extern int prefresh ( WINDOW *, int, int, int, int, int, int );
+extern int printw ( char *, ... );
+extern int putp ( const char * );
+extern void qiflush ( void );
+extern int raw ( void );
+//extern int redrawwin ( WINDOW * );
+//extern int refresh ( void );
+extern int reset_prog_mode ( void );
+extern int reset_shell_mode ( void );
+extern int resetty ( void );
+extern int ripoffline ( int, int (*) ( WINDOW *, int) );
+extern int savetty ( void );
+//extern int scanw ( char *, ... );
+//extern int scrl ( int );
+//extern int scroll ( WINDOW * );
+//extern int scrollok ( WINDOW *, bool );
+//extern int setscrreg ( int, int );
+extern SCREEN *set_term ( SCREEN * );
+extern int setupterm ( char *, int, int * );
+extern int slk_attr_off ( const attr_t, void * );
+extern int slk_attroff ( const chtype );
+extern int slk_attr_on ( const attr_t, void * );
+extern int slk_attron ( const chtype );
+extern int slk_attr_set ( const attr_t, short, void * );
+extern int slk_attrset ( const chtype );
+extern int slk_clear ( void );
+extern int slk_colour ( short );
+#define slk_color( c ) slk_colour( (c) )
+extern int slk_init ( int );
+extern char *slk_label ( int );
+extern int slk_noutrefresh ( void );
+//extern int slk_refresh ( void );
+extern int slk_restore ( void );
+extern int slk_set ( int, const char *, int ) __nonnull;
+extern int slk_touch ( void );
+extern int standend ( void );
+extern int standout ( void );
+//extern int start_colour ( void );
+#define start_color() start_colour()
+//extern WINDOW *subpad ( WINDOW *, int, int, int, int );
+extern WINDOW *subwin ( WINDOW *, int, int, int, int ) __nonnull;
+extern int syncok ( WINDOW *, bool );
+extern chtype termattrs ( void );
+extern attr_t term_attrs ( void );
+extern char *termname ( void );
+extern int tigetflag ( char * );
+extern int tigetnum ( char * );
+extern char *tigetstr ( char * );
+extern void timeout ( int );
+//extern int touchline ( WINDOW *, int, int );
+//extern int touchwin ( WINDOW * );
+extern char *tparm ( char *, long, long, long, long, long, long, long, long,
+ long );
+extern int typeahead ( int );
+//extern int ungetch ( int );
+//extern int untouchwin ( WINDOW * );
+extern void use_env ( bool );
+extern int vid_attr ( attr_t, short, void * );
+extern int vidattr ( chtype );
+extern int vid_puts ( attr_t, short, void *, int ( *) ( int) );
+extern int vidputs ( chtype, int ( *) ( int) );
+//extern int vline ( chtype, int );
+//extern int vwprintw ( WINDOW *, const char *, va_list );
+extern int vw_printw ( WINDOW *, const char *, va_list ) __nonnull;
+//extern int vwscanw ( WINDOW *, char *, va_list );
+//extern int vw_scanw ( WINDOW *, char *, va_list );
+extern int waddch ( WINDOW *, const chtype ) __nonnull;
+extern int waddchnstr ( WINDOW *, const chtype *, int ) __nonnull;
+//extern int waddchstr ( WINDOW *, const chtype * );
+extern int waddnstr ( WINDOW *, const char *, int ) __nonnull;
+//extern int waddstr ( WINDOW *, const char * );
+extern int wattroff ( WINDOW *, int ) __nonnull;
+extern int wattron ( WINDOW *, int ) __nonnull;
+extern int wattrset ( WINDOW *, int ) __nonnull;
+extern int wattr_get ( WINDOW *, attr_t *, short *, void * )
+ __attribute__ (( nonnull (1, 2, 3)));
+extern int wattr_off ( WINDOW *, attr_t, void * )
+ __attribute__ (( nonnull (1)));
+extern int wattr_on ( WINDOW *, attr_t, void * )
+ __attribute__ (( nonnull (1)));
+extern int wattr_set ( WINDOW *, attr_t, short, void * )
+ __attribute__ (( nonnull (1)));
+//extern void wbkgdset ( WINDOW *, chtype );
+extern int wborder ( WINDOW *, chtype, chtype, chtype, chtype, chtype, chtype,
+ chtype, chtype ) __nonnull;
+extern int wclrtobot ( WINDOW * ) __nonnull;
+extern int wclrtoeol ( WINDOW * ) __nonnull;
+extern void wcursyncup ( WINDOW * );
+extern int wcolour_set ( WINDOW *, short, void * ) __nonnull;
+#define wcolor_set(w,s,v) wcolour_set((w),(s),(v))
+extern int wdelch ( WINDOW * ) __nonnull;
+extern int wdeleteln ( WINDOW * ) __nonnull;
+extern int wechochar ( WINDOW *, const chtype );
+extern int werase ( WINDOW * ) __nonnull;
+extern int wgetch ( WINDOW * );
+extern int wgetnstr ( WINDOW *, char *, int );
+//extern int wgetstr ( WINDOW *, char * );
+extern int whline ( WINDOW *, chtype, int ) __nonnull;
+//extern chtype winch ( WINDOW * );
+//extern int winchnstr ( WINDOW *, chtype *, int );
+//extern int winchstr ( WINDOW *, chtype * );
+//extern int winnstr ( WINDOW *, char *, int );
+//extern int winsch ( WINDOW *, chtype );
+//extern int winsnstr ( WINDOW *, const char *, int );
+//extern int winsstr ( WINDOW *, const char * );
+//extern int winstr ( WINDOW *, char * );
+extern int wmove ( WINDOW *, int, int );
+//extern int wnoutrefresh ( WINDOW * );
+extern int wprintw ( WINDOW *, const char *, ... ) __nonnull;
+//extern int wredrawln ( WINDOW *, int, int );
+//extern int wrefresh ( WINDOW * );
+//extern int wscanw ( WINDOW *, char *, ... );
+//extern int wscrl ( WINDOW *, int );
+//extern int wsetscrreg ( WINDOW *, int, int );
+//extern int wstandend ( WINDOW * );
+//extern int wstandout ( WINDOW * );
+extern void wsyncup ( WINDOW * );
+extern void wsyncdown ( WINDOW * );
+extern void wtimeout ( WINDOW *, int );
+//extern int wtouchln ( WINDOW *, int, int, int );
+extern int wvline ( WINDOW *, chtype, int ) __nonnull;
+
+/*
+ * There is frankly a ridiculous amount of redundancy within the
+ * curses API - ncurses decided to get around this by using #define
+ * macros, but I've decided to be type-safe and implement them all as
+ * static inlines instead...
+ */
+
+static inline int addch ( const chtype ch ) {
+ return waddch( stdscr, ch );
+}
+
+static inline int addchnstr ( const chtype *chstr, int n ) {
+ return waddchnstr ( stdscr, chstr, n );
+}
+
+static inline int addchstr ( const chtype *chstr ) {
+ return waddchnstr ( stdscr, chstr, -1 );
+}
+
+static inline int addnstr ( const char *str, int n ) {
+ return waddnstr ( stdscr, str, n );
+}
+
+static inline int addstr ( const char *str ) {
+ return waddnstr ( stdscr, str, -1 );
+}
+
+static inline int attroff ( int attrs ) {
+ return wattroff ( stdscr, attrs );
+}
+
+static inline int attron ( int attrs ) {
+ return wattron ( stdscr, attrs );
+}
+
+static inline int attrset ( int attrs ) {
+ return wattrset ( stdscr, attrs );
+}
+
+static inline int attr_get ( attr_t *attrs, short *pair, void *opts ) {
+ return wattr_get ( stdscr, attrs, pair, opts );
+}
+
+static inline int attr_off ( attr_t attrs, void *opts ) {
+ return wattr_off ( stdscr, attrs, opts );
+}
+
+static inline int attr_on ( attr_t attrs, void *opts ) {
+ return wattr_on ( stdscr, attrs, opts );
+}
+
+static inline int attr_set ( attr_t attrs, short cpair, void *opts ) {
+ return wattr_set ( stdscr, attrs, cpair, opts );
+}
+
+static inline void bkgdset ( chtype ch ) {
+ wattrset ( stdscr, ch );
+}
+
+static inline int border ( chtype ls, chtype rs, chtype ts, chtype bs,
+ chtype tl, chtype tr, chtype bl, chtype br ) {
+ return wborder ( stdscr, ls, rs, ts, bs, tl, tr, bl, br );
+}
+
+static inline bool can_change_colour ( void ) {
+ return FALSE;
+}
+
+static inline int clrtobot ( void ) {
+ return wclrtobot( stdscr );
+}
+
+static inline int clrtoeol ( void ) {
+ return wclrtoeol( stdscr );
+}
+
+static inline int colour_set ( short colour_pair_number, void *opts ) {
+ return wcolour_set ( stdscr, colour_pair_number, opts );
+}
+
+static inline int delch ( void ) {
+ return wdelch ( stdscr );
+}
+
+static inline int deleteln ( void ) {
+ return wdeleteln( stdscr );
+}
+
+static inline int erase ( void ) {
+ return werase ( stdscr );
+}
+
+static inline int getch ( void ) {
+ return wgetch ( stdscr );
+}
+
+static inline int getnstr ( char *str, int n ) {
+ return wgetnstr ( stdscr, str, n );
+}
+
+static inline int getstr ( char *str ) {
+ return wgetnstr ( stdscr, str, -1 );
+}
+
+static inline bool has_colors ( void ) {
+ return TRUE;
+}
+
+static inline int has_key ( int kc __unused ) {
+ return TRUE;
+}
+
+static inline int hline ( chtype ch, int n ) {
+ return whline ( stdscr, ch, n );
+}
+
+static inline int move ( int y, int x ) {
+ return wmove ( stdscr, y, x );
+}
+
+static inline int mvaddch ( int y, int x, const chtype ch ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? waddch( stdscr, ch ) : ERR );
+}
+
+static inline int mvaddchnstr ( int y, int x, const chtype *chstr, int n ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? waddchnstr ( stdscr, chstr, n ) : ERR );
+}
+
+static inline int mvaddchstr ( int y, int x, const chtype *chstr ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? waddchnstr ( stdscr, chstr, -1 ) : ERR );
+}
+
+static inline int mvaddnstr ( int y, int x, const char *str, int n ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? waddnstr ( stdscr, str, n ) : ERR );
+}
+
+static inline int mvaddstr ( int y, int x, const char *str ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? waddnstr ( stdscr, str, -1 ) : ERR );
+}
+
+static inline int mvdelch ( int y, int x ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? wdelch ( stdscr ) : ERR );
+}
+
+static inline int mvgetch ( int y, int x ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? wgetch ( stdscr ) : ERR );
+}
+
+static inline int mvgetnstr ( int y, int x, char *str, int n ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? wgetnstr ( stdscr, str, n ) : ERR );
+}
+
+static inline int mvgetstr ( int y, int x, char *str ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? wgetnstr ( stdscr, str, -1 ) : ERR );
+}
+
+static inline int mvhline ( int y, int x, chtype ch, int n ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? whline ( stdscr, ch, n ) : ERR );
+}
+
+// OK, so maybe a few I did with macros...
+#define mvprintw( y, x, fmt, ... ) \
+ ( wmove(stdscr,(y),(x)) == OK \
+ ? wprintw( stdscr,(fmt), ## __VA_ARGS__ ) : ERR )
+
+static inline int mvvline ( int y, int x, chtype ch, int n ) {
+ return ( wmove ( stdscr, y, x ) == OK
+ ? wvline ( stdscr, ch, n ) : ERR );
+}
+
+static inline int mvwaddch ( WINDOW *win, int y, int x, const chtype ch ) {
+ return ( wmove( win, y, x ) == OK
+ ? waddch ( win, ch ) : ERR );
+}
+
+static inline int mvwaddchnstr ( WINDOW *win, int y, int x, const chtype *chstr, int n ) {
+ return ( wmove ( win, y, x ) == OK
+ ? waddchnstr ( win, chstr, n ) : ERR );
+}
+
+static inline int mvwaddchstr ( WINDOW *win, int y, int x, const chtype *chstr ) {
+ return ( wmove ( win, y, x ) == OK
+ ? waddchnstr ( win, chstr, -1 ) : ERR );
+}
+
+static inline int mvwaddnstr ( WINDOW *win, int y, int x, const char *str, int n ) {
+ return ( wmove ( win, y, x ) == OK
+ ? waddnstr ( win, str, n ) : ERR );
+}
+
+static inline int mvwaddstr ( WINDOW *win, int y, int x, const char *str ) {
+ return ( wmove ( win, y, x ) == OK
+ ? waddnstr ( win, str, -1 ) : ERR );
+}
+
+static inline int mvwdelch ( WINDOW *win, int y, int x ) {
+ return ( wmove ( win, y, x ) == OK
+ ? wdelch ( win ) : ERR );
+}
+
+static inline int mvwgetch ( WINDOW *win, int y, int x ) {
+ return ( wmove ( win, y, x ) == OK
+ ? wgetch ( win ) : ERR );
+}
+
+static inline int mvwgetnstr ( WINDOW *win, int y, int x, char *str, int n ) {
+ return ( wmove ( win, y, x ) == OK
+ ? wgetnstr ( win, str, n ) : ERR );
+}
+
+static inline int mvwgetstr ( WINDOW *win, int y, int x, char *str ) {
+ return ( wmove ( win, y, x ) == OK
+ ? wgetnstr ( win, str, -1 ) : ERR );
+}
+
+static inline int mvwhline ( WINDOW *win, int y, int x, chtype ch, int n ) {
+ return ( wmove ( win, y, x ) == OK
+ ? whline ( win, ch, n ) : ERR );
+}
+
+#define mvwprintw( win, y, x, fmt, ... ) \
+ ( wmove((win),(y),(x)) == OK \
+ ? wprintw((win),(fmt), ## __VA_ARGS__) : ERR )
+
+static inline int mvwvline ( WINDOW *win, int y, int x, chtype ch, int n ) {
+ return ( wmove ( win, y, x ) == OK
+ ? wvline ( win, ch, n ) : ERR );
+}
+
+#define printw( fmt, ... ) wprintw(stdscr,(fmt), ## __VA_ARGS__ )
+
+static inline int slk_refresh ( void ) {
+ if ( slk_clear() == OK )
+ return slk_restore();
+ else
+ return ERR;
+}
+
+#define standend() wstandend( stdscr )
+#define standout() wstandout( stdscr )
+
+static inline int start_colour ( void ) {
+ return OK;
+}
+
+static inline int vline ( chtype ch, int n ) {
+ return wvline ( stdscr, ch, n );
+}
+
+// marked for removal
+static inline int vwprintw ( WINDOW *win, const char *fmt, va_list varglist ) {
+ return vw_printw ( win, fmt, varglist );
+}
+
+static inline int waddchstr ( WINDOW *win, const chtype *chstr ) {
+ return waddchnstr ( win, chstr, -1 );
+}
+
+static inline int waddstr ( WINDOW *win, const char *str ) {
+ return waddnstr ( win, str, -1 );
+}
+
+static inline int wbkgdset ( WINDOW *win, chtype ch ) {
+ return wattrset( win, ch );
+}
+
+static inline int wgetstr ( WINDOW *win, char *str ) {
+ return wgetnstr ( win, str, -1 );
+}
+
+static inline int wstandend ( WINDOW *win ) {
+ return wattrset ( win, A_DEFAULT );
+}
+
+static inline int wstandout ( WINDOW *win ) {
+ return wattrset ( win, A_STANDOUT );
+}
+
+#endif /* CURSES_H */
diff --git a/gpxe/src/include/debug.h b/gpxe/src/include/debug.h
new file mode 100644
index 00000000..bb5d33f3
--- /dev/null
+++ b/gpxe/src/include/debug.h
@@ -0,0 +1,28 @@
+#ifndef DEBUG_H
+#define DEBUG_H
+
+//#include <lib.h>
+extern int last_putchar;
+
+/* Defining DEBUG_THIS before including this file enables debug() macro
+ * for the file. DEBUG_ALL is for global control. */
+
+#if DEBUG_THIS || DEBUG_ALL
+#define DEBUG 1
+#else
+#undef DEBUG
+#endif
+
+#if DEBUG
+# define debug(...) \
+ ((last_putchar=='\n' ? printf("%s: ", __FUNCTION__) : 0), \
+ printf(__VA_ARGS__))
+# define debug_hexdump hexdump
+#else
+# define debug(...) /* nothing */
+# define debug_hexdump(...) /* nothing */
+#endif
+
+#define debugx debug
+
+#endif /* DEBUG_H */
diff --git a/gpxe/src/include/dhcp.h b/gpxe/src/include/dhcp.h
new file mode 100644
index 00000000..deba219b
--- /dev/null
+++ b/gpxe/src/include/dhcp.h
@@ -0,0 +1,12 @@
+#ifndef DHCP_H
+#define DHCP_H
+
+#include "stdint.h"
+
+struct dhcp_dev_id {
+ uint8_t bus_type;
+ uint16_t vendor_id;
+ uint16_t device_id;
+} __attribute__ (( packed ));
+
+#endif /* DHCP_H */
diff --git a/gpxe/src/include/elf.h b/gpxe/src/include/elf.h
new file mode 100644
index 00000000..a6eb5d9c
--- /dev/null
+++ b/gpxe/src/include/elf.h
@@ -0,0 +1,236 @@
+#ifndef ELF_H
+#define ELF_H
+
+#define EI_NIDENT 16 /* Size of e_ident array. */
+
+/* Values for e_type. */
+#define ET_NONE 0 /* No file type */
+#define ET_REL 1 /* Relocatable file */
+#define ET_EXEC 2 /* Executable file */
+#define ET_DYN 3 /* Shared object file */
+#define ET_CORE 4 /* Core file */
+
+/* Values for e_machine (architecute). */
+#define EM_NONE 0 /* No machine */
+#define EM_M32 1 /* AT&T WE 32100 */
+#define EM_SPARC 2 /* SUN SPARC */
+#define EM_386 3 /* Intel 80386+ */
+#define EM_68K 4 /* Motorola m68k family */
+#define EM_88K 5 /* Motorola m88k family */
+#define EM_486 6 /* Perhaps disused */
+#define EM_860 7 /* Intel 80860 */
+#define EM_MIPS 8 /* MIPS R3000 big-endian */
+#define EM_S370 9 /* IBM System/370 */
+#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */
+
+#define EM_PARISC 15 /* HPPA */
+#define EM_VPP500 17 /* Fujitsu VPP500 */
+#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
+#define EM_960 19 /* Intel 80960 */
+#define EM_PPC 20 /* PowerPC */
+#define EM_PPC64 21 /* PowerPC 64-bit */
+#define EM_S390 22 /* IBM S390 */
+
+#define EM_V800 36 /* NEC V800 series */
+#define EM_FR20 37 /* Fujitsu FR20 */
+#define EM_RH32 38 /* TRW RH-32 */
+#define EM_RCE 39 /* Motorola RCE */
+#define EM_ARM 40 /* ARM */
+#define EM_FAKE_ALPHA 41 /* Digital Alpha */
+#define EM_SH 42 /* Hitachi SH */
+#define EM_SPARCV9 43 /* SPARC v9 64-bit */
+#define EM_TRICORE 44 /* Siemens Tricore */
+#define EM_ARC 45 /* Argonaut RISC Core */
+#define EM_H8_300 46 /* Hitachi H8/300 */
+#define EM_H8_300H 47 /* Hitachi H8/300H */
+#define EM_H8S 48 /* Hitachi H8S */
+#define EM_H8_500 49 /* Hitachi H8/500 */
+#define EM_IA_64 50 /* Intel Merced */
+#define EM_MIPS_X 51 /* Stanford MIPS-X */
+#define EM_COLDFIRE 52 /* Motorola Coldfire */
+#define EM_68HC12 53 /* Motorola M68HC12 */
+#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/
+#define EM_PCP 55 /* Siemens PCP */
+#define EM_NCPU 56 /* Sony nCPU embeeded RISC */
+#define EM_NDR1 57 /* Denso NDR1 microprocessor */
+#define EM_STARCORE 58 /* Motorola Start*Core processor */
+#define EM_ME16 59 /* Toyota ME16 processor */
+#define EM_ST100 60 /* STMicroelectronic ST100 processor */
+#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/
+#define EM_X86_64 62 /* AMD x86-64 architecture */
+#define EM_PDSP 63 /* Sony DSP Processor */
+
+#define EM_FX66 66 /* Siemens FX66 microcontroller */
+#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */
+#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */
+#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */
+#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */
+#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */
+#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */
+#define EM_SVX 73 /* Silicon Graphics SVx */
+#define EM_AT19 74 /* STMicroelectronics ST19 8 bit mc */
+#define EM_VAX 75 /* Digital VAX */
+#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */
+#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */
+#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */
+#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */
+#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */
+#define EM_HUANY 81 /* Harvard University machine-independent object files */
+#define EM_PRISM 82 /* SiTera Prism */
+#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */
+#define EM_FR30 84 /* Fujitsu FR30 */
+#define EM_D10V 85 /* Mitsubishi D10V */
+#define EM_D30V 86 /* Mitsubishi D30V */
+#define EM_V850 87 /* NEC v850 */
+#define EM_M32R 88 /* Mitsubishi M32R */
+#define EM_MN10300 89 /* Matsushita MN10300 */
+#define EM_MN10200 90 /* Matsushita MN10200 */
+#define EM_PJ 91 /* picoJava */
+#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */
+#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */
+#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */
+#define EM_NUM 95
+
+/* Values for p_type. */
+#define PT_NULL 0 /* Unused entry. */
+#define PT_LOAD 1 /* Loadable segment. */
+#define PT_DYNAMIC 2 /* Dynamic linking information segment. */
+#define PT_INTERP 3 /* Pathname of interpreter. */
+#define PT_NOTE 4 /* Auxiliary information. */
+#define PT_SHLIB 5 /* Reserved (not used). */
+#define PT_PHDR 6 /* Location of program header itself. */
+
+/* Values for p_flags. */
+#define PF_X 0x1 /* Executable. */
+#define PF_W 0x2 /* Writable. */
+#define PF_R 0x4 /* Readable. */
+
+
+#define ELF_PROGRAM_RETURNS_BIT 0x8000000 /* e_flags bit 31 */
+
+#define EI_MAG0 0
+#define ELFMAG0 0x7f
+
+#define EI_MAG1 1
+#define ELFMAG1 'E'
+
+#define EI_MAG2 2
+#define ELFMAG2 'L'
+
+#define EI_MAG3 3
+#define ELFMAG3 'F'
+
+#define ELFMAG "\177ELF"
+#define SELFMAG 4
+
+#define EI_CLASS 4 /* File class byte index */
+#define ELFCLASSNONE 0 /* Invalid class */
+#define ELFCLASS32 1 /* 32-bit objects */
+#define ELFCLASS64 2 /* 64-bit objects */
+
+#define EI_DATA 5 /* Data encodeing byte index */
+#define ELFDATANONE 0 /* Invalid data encoding */
+#define ELFDATA2LSB 1 /* 2's complement little endian */
+#define ELFDATA2MSB 2 /* 2's complement big endian */
+
+#define EI_VERSION 6 /* File version byte index */
+ /* Value must be EV_CURRENT */
+
+#define EV_NONE 0 /* Invalid ELF Version */
+#define EV_CURRENT 1 /* Current version */
+
+#define ELF32_PHDR_SIZE (8*4) /* Size of an elf program header */
+
+#ifndef ASSEMBLY
+
+#include <stdint.h>
+
+/*
+ * ELF definitions common to all 32-bit architectures.
+ */
+
+typedef uint32_t Elf32_Addr;
+typedef uint16_t Elf32_Half;
+typedef uint32_t Elf32_Off;
+typedef int32_t Elf32_Sword;
+typedef uint32_t Elf32_Word;
+typedef uint32_t Elf32_Size;
+
+typedef uint64_t Elf64_Addr;
+typedef uint16_t Elf64_Half;
+typedef uint64_t Elf64_Off;
+typedef int32_t Elf64_Sword;
+typedef uint32_t Elf64_Word;
+typedef uint64_t Elf64_Size;
+
+/*
+ * ELF header.
+ */
+typedef struct {
+ unsigned char e_ident[EI_NIDENT]; /* File identification. */
+ Elf32_Half e_type; /* File type. */
+ Elf32_Half e_machine; /* Machine architecture. */
+ Elf32_Word e_version; /* ELF format version. */
+ Elf32_Addr e_entry; /* Entry point. */
+ Elf32_Off e_phoff; /* Program header file offset. */
+ Elf32_Off e_shoff; /* Section header file offset. */
+ Elf32_Word e_flags; /* Architecture-specific flags. */
+ Elf32_Half e_ehsize; /* Size of ELF header in bytes. */
+ Elf32_Half e_phentsize; /* Size of program header entry. */
+ Elf32_Half e_phnum; /* Number of program header entries. */
+ Elf32_Half e_shentsize; /* Size of section header entry. */
+ Elf32_Half e_shnum; /* Number of section header entries. */
+ Elf32_Half e_shstrndx; /* Section name strings section. */
+} Elf32_Ehdr;
+
+typedef struct {
+ unsigned char e_ident[EI_NIDENT]; /* File identification. */
+ Elf64_Half e_type; /* File type. */
+ Elf64_Half e_machine; /* Machine architecture. */
+ Elf64_Word e_version; /* ELF format version. */
+ Elf64_Addr e_entry; /* Entry point. */
+ Elf64_Off e_phoff; /* Program header file offset. */
+ Elf64_Off e_shoff; /* Section header file offset. */
+ Elf64_Word e_flags; /* Architecture-specific flags. */
+ Elf64_Half e_ehsize; /* Size of ELF header in bytes. */
+ Elf64_Half e_phentsize; /* Size of program header entry. */
+ Elf64_Half e_phnum; /* Number of program header entries. */
+ Elf64_Half e_shentsize; /* Size of section header entry. */
+ Elf64_Half e_shnum; /* Number of section header entries. */
+ Elf64_Half e_shstrndx; /* Section name strings section. */
+} Elf64_Ehdr;
+
+/*
+ * Program header.
+ */
+typedef struct {
+ Elf32_Word p_type; /* Entry type. */
+ Elf32_Off p_offset; /* File offset of contents. */
+ Elf32_Addr p_vaddr; /* Virtual address (not used). */
+ Elf32_Addr p_paddr; /* Physical address. */
+ Elf32_Size p_filesz; /* Size of contents in file. */
+ Elf32_Size p_memsz; /* Size of contents in memory. */
+ Elf32_Word p_flags; /* Access permission flags. */
+ Elf32_Size p_align; /* Alignment in memory and file. */
+} Elf32_Phdr;
+
+typedef struct {
+ Elf64_Word p_type; /* Entry type. */
+ Elf64_Word p_flags; /* Access permission flags. */
+ Elf64_Off p_offset; /* File offset of contents. */
+ Elf64_Addr p_vaddr; /* Virtual address (not used). */
+ Elf64_Addr p_paddr; /* Physical address. */
+ Elf64_Size p_filesz; /* Size of contents in file. */
+ Elf64_Size p_memsz; /* Size of contents in memory. */
+ Elf64_Size p_align; /* Alignment in memory and file. */
+} Elf64_Phdr;
+
+/* Standardized Elf image notes for booting... The name for all of these is ELFBoot */
+
+
+/* ELF Defines for the current architecture */
+#include "bits/elf.h"
+
+#endif /* ASSEMBLY */
+
+#endif /* ELF_H */
diff --git a/gpxe/src/include/endian.h b/gpxe/src/include/endian.h
new file mode 100644
index 00000000..32006224
--- /dev/null
+++ b/gpxe/src/include/endian.h
@@ -0,0 +1,19 @@
+#ifndef ETHERBOOT_ENDIAN_H
+#define ETHERBOOT_ENDIAN_H
+
+/* Definitions for byte order, according to significance of bytes,
+ from low addresses to high addresses. The value is what you get by
+ putting '4' in the most significant byte, '3' in the second most
+ significant byte, '2' in the second least significant byte, and '1'
+ in the least significant byte, and then writing down one digit for
+ each byte, starting with the byte at the lowest address at the left,
+ and proceeding to the byte with the highest address at the right. */
+
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#define __PDP_ENDIAN 3412
+
+#include "bits/endian.h"
+
+
+#endif /* ETHERBOOT_ENDIAN_H */
diff --git a/gpxe/src/include/errno.h b/gpxe/src/include/errno.h
new file mode 100644
index 00000000..58dff1fd
--- /dev/null
+++ b/gpxe/src/include/errno.h
@@ -0,0 +1,508 @@
+#ifndef ERRNO_H
+#define ERRNO_H
+
+/** @file
+ *
+ * Error codes
+ *
+ * Return status codes as used within gPXE are designed to allow for
+ * maximum visibility into the source of an error even in an end-user
+ * build with no debugging. They are constructed as follows:
+ *
+ * Bits 7-0 : PXE error code
+ *
+ * This is the closest equivalent PXE error code
+ * (e.g. PXENV_STATUS_OUT_OF_RESOURCES), and is the only part of the
+ * error that will be returned via the PXE API, since PXE has
+ * predefined error codes.
+ *
+ * Bits 12-8 : Per-file disambiguator
+ *
+ * When the same error number can be generated from multiple points
+ * within a file, this field can be used to identify the unique
+ * instance.
+ *
+ * Bits 23-13 : File identifier
+ *
+ * This is a unique identifier for the file generating the error
+ * (e.g. ERRFILE_tcp for tcp.c).
+ *
+ * Bits 30-24 : POSIX error code
+ *
+ * This is the closest equivalent POSIX error code (e.g. ENOMEM).
+ *
+ * Bit 31 : Reserved
+ *
+ * Errors are usually return as negative error numbers (e.g. -EINVAL);
+ * bit 31 is therefore unusable.
+ *
+ *
+ * The convention within the code is that errors are negative and
+ * expressed using the POSIX error code and (optionally) a per-file
+ * disambiguator, e.g.
+ *
+ * return -EINVAL;
+ *
+ * or
+ *
+ * #define ETCP_BAD_CHECKSUM EUNIQ_02
+ * return -( EINVAL | ETCP_BAD_CHECKSUM )
+ *
+ * By various bits of preprocessor magic, the PXE error code and file
+ * identifier are already incorporated into the definition of the
+ * POSIX error code, which keeps the code relatively clean.
+ *
+ *
+ * Functions that wish to return failures should be declared as
+ * returning an integer @c rc "Return status code". A return value of
+ * zero indicates success, a non-zero value indicates failure. The
+ * return value can be passed directly to strerror() in order to
+ * generate a human-readable error message, e.g.
+ *
+ * if ( ( rc = some_function ( ... ) ) != 0 ) {
+ * DBG ( "Whatever I was trying to do failed: %s\n", strerror ( rc ) );
+ * return rc;
+ * }
+ *
+ * As illustrated in the above example, error returns should generally
+ * be directly propagated upward to the calling function.
+ *
+ */
+
+/* Get definitions for file identifiers */
+#include <gpxe/errfile.h>
+
+/* If we do not have a valid file identifier, generate a compiler
+ * warning upon usage of any error codes. (Don't just use a #warning,
+ * because some files include errno.h but don't ever actually use any
+ * error codes.)
+ */
+#if ! ERRFILE
+extern char missing_errfile_declaration[] __attribute__ (( deprecated ));
+#undef ERRFILE
+#define ERRFILE ( 0 * ( ( int ) missing_errfile_declaration ) )
+#endif
+
+/** Derive PXENV_STATUS code from gPXE error number */
+#define PXENV_STATUS( rc ) ( (-(rc)) & 0x00ff )
+
+/**
+ * @defgroup pxeerrors PXE error codes
+ *
+ * The names, meanings and values of these error codes are defined by
+ * the PXE specification.
+ *
+ * @{
+ */
+
+/* Generic errors */
+#define PXENV_STATUS_SUCCESS 0x0000
+#define PXENV_STATUS_FAILURE 0x0001
+#define PXENV_STATUS_BAD_FUNC 0x0002
+#define PXENV_STATUS_UNSUPPORTED 0x0003
+#define PXENV_STATUS_KEEP_UNDI 0x0004
+#define PXENV_STATUS_KEEP_ALL 0x0005
+#define PXENV_STATUS_OUT_OF_RESOURCES 0x0006
+
+/* ARP errors (0x0010 to 0x001f) */
+#define PXENV_STATUS_ARP_TIMEOUT 0x0011
+
+/* Base-Code state errors */
+#define PXENV_STATUS_UDP_CLOSED 0x0018
+#define PXENV_STATUS_UDP_OPEN 0x0019
+#define PXENV_STATUS_TFTP_CLOSED 0x001a
+#define PXENV_STATUS_TFTP_OPEN 0x001b
+
+/* BIOS/system errors (0x0020 to 0x002f) */
+#define PXENV_STATUS_MCOPY_PROBLEM 0x0020
+#define PXENV_STATUS_BIS_INTEGRITY_FAILURE 0x0021
+#define PXENV_STATUS_BIS_VALIDATE_FAILURE 0x0022
+#define PXENV_STATUS_BIS_INIT_FAILURE 0x0023
+#define PXENV_STATUS_BIS_SHUTDOWN_FAILURE 0x0024
+#define PXENV_STATUS_BIS_GBOA_FAILURE 0x0025
+#define PXENV_STATUS_BIS_FREE_FAILURE 0x0026
+#define PXENV_STATUS_BIS_GSI_FAILURE 0x0027
+#define PXENV_STATUS_BIS_BAD_CKSUM 0x0028
+
+/* TFTP/MTFTP errors (0x0030 to 0x003f) */
+#define PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS 0x0030
+#define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x0032
+#define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x0033
+#define PXENV_STATUS_TFTP_READ_TIMEOUT 0x0035
+#define PXENV_STATUS_TFTP_ERROR_OPCODE 0x0036
+#define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION 0x0038
+#define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION 0x0039
+#define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES 0x003a
+#define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x003b
+#define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x003c
+#define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x003d
+#define PXENV_STATUS_TFTP_NO_FILESIZE 0x003e
+#define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE 0x003f
+
+/* Reserved errors 0x0040 to 0x004f) */
+
+/* DHCP/BOOTP errors (0x0050 to 0x005f) */
+#define PXENV_STATUS_DHCP_TIMEOUT 0x0051
+#define PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x0052
+#define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x0053
+#define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x0054
+
+/* Driver errors (0x0060 to 0x006f) */
+#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x0060
+#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x0061
+#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x0062
+#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x0063
+#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x0064
+#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x0065
+#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x0066
+#define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x0067
+#define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM 0x0068
+#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x0069
+#define PXENV_STATUS_UNDI_INVALID_STATE 0x006a
+#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x006b
+#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x006c
+
+/* ROM and NBP bootstrap errors (0x0070 to 0x007f) */
+#define PXENV_STATUS_BSTRAP_PROMPT_MENU 0x0074
+#define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x0076
+#define PXENV_STATUS_BSTRAP_MISSING_LIST 0x0077
+#define PXENV_STATUS_BSTRAP_NO_RESPONSE 0x0078
+#define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x0079
+
+/* Environment NBP errors (0x0080 to 0x008f) */
+
+/* Reserved errors (0x0090 to 0x009f) */
+
+/* Miscellaneous errors (0x00a0 to 0x00af) */
+#define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE 0x00a0
+#define PXENV_STATUS_BINL_NO_PXE_SERVER 0x00a1
+#define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE 0x00a2
+#define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE 0x00a3
+
+/* BUSD errors (0x00b0 to 0x00bf) */
+#define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED 0x00b0
+
+/* Loader errors (0x00c0 to 0x00cf) */
+#define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY 0x00c0
+#define PXENV_STATUS_LOADER_NO_BC_ROMID 0x00c1
+#define PXENV_STATUS_LOADER_BAD_BC_ROMID 0x00c2
+#define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE 0x00c3
+#define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0x00c4
+#define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0x00c5
+#define PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE 0x00c6
+#define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0x00c8
+#define PXENV_STATUS_LOADER_NO_PXENV_STRUCT 0x00c9
+#define PXENV_STATUS_LOADER_UNDI_START 0x00ca
+#define PXENV_STATUS_LOADER_BC_START 0x00cb
+
+/** @} */
+
+/**
+ * @defgroup posixerrors POSIX error codes
+ *
+ * The names and meanings (but not the values) of these error codes
+ * are defined by POSIX. We choose to assign unique values which
+ * incorporate the closest equivalent PXE error code, so that code may
+ * simply use ENOMEM, rather than having to use the cumbersome
+ * (ENOMEM|PXENV_STATUS_OUT_OF_RESOURCES).
+ *
+ * @{
+ */
+
+/** Operation completed successfully */
+#define ENOERR ( ERRFILE | PXENV_STATUS_SUCCESS | 0x00000000 )
+
+/** Arg list too long */
+#define E2BIG ( ERRFILE | PXENV_STATUS_BAD_FUNC | 0x01000000 )
+
+/** Permission denied */
+#define EACCES ( ERRFILE | PXENV_STATUS_TFTP_ACCESS_VIOLATION | 0x02000000 )
+
+/** Address in use */
+#define EADDRINUSE ( ERRFILE | PXENV_STATUS_UDP_OPEN | 0x03000000 )
+
+/** Address not available */
+#define EADDRNOTAVAIL ( ERRFILE | PXENV_STATUS_UDP_OPEN | 0x04000000 )
+
+/** Address family not supported */
+#define EAFNOSUPPORT ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x05000000 )
+
+/** Resource temporarily unavailable */
+#define EAGAIN ( ERRFILE | PXENV_STATUS_FAILURE | 0x06000000 )
+
+/** Connection already in progress */
+#define EALREADY ( ERRFILE | PXENV_STATUS_UDP_OPEN | 0x07000000 )
+
+/** Bad file descriptor */
+#define EBADF ( ERRFILE | PXENV_STATUS_TFTP_CLOSED | 0x08000000 )
+
+/** Bad message */
+#define EBADMSG ( ERRFILE | PXENV_STATUS_FAILURE | 0x09000000 )
+
+/** Resource busy */
+#define EBUSY ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x0a000000 )
+
+/** Operation canceled */
+#define ECANCELED \
+ ( ERRFILE | PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE | 0x0b000000 )
+
+/** No child processes */
+#define ECHILD ( ERRFILE | PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x0c000000 )
+
+/** Connection aborted */
+#define ECONNABORTED \
+ ( ERRFILE | PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION | 0x0d000000 )
+
+/** Connection refused */
+#define ECONNREFUSED \
+ ( ERRFILE | PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION | 0x0e000000 )
+
+/** Connection reset */
+#define ECONNRESET \
+ ( ERRFILE | PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION | 0x0f000000 )
+
+/** Resource deadlock avoided */
+#define EDEADLK ( ERRFILE | PXENV_STATUS_FAILURE | 0x10000000 )
+
+/** Destination address required */
+#define EDESTADDRREQ ( ERRFILE | PXENV_STATUS_BAD_FUNC | 0x11000000 )
+
+/** Domain error */
+#define EDOM ( ERRFILE | PXENV_STATUS_FAILURE | 0x12000000 )
+
+/** Reserved */
+#define EDQUOT ( ERRFILE | PXENV_STATUS_FAILURE | 0x13000000 )
+
+/** File exists */
+#define EEXIST ( ERRFILE | PXENV_STATUS_FAILURE | 0x14000000 )
+
+/** Bad address */
+#define EFAULT ( ERRFILE | PXENV_STATUS_MCOPY_PROBLEM | 0x15000000 )
+
+/** File too large */
+#define EFBIG ( ERRFILE | PXENV_STATUS_MCOPY_PROBLEM | 0x16000000 )
+
+/** Host is unreachable */
+#define EHOSTUNREACH ( ERRFILE | PXENV_STATUS_ARP_TIMEOUT | 0x17000000 )
+
+/** Identifier removed */
+#define EIDRM ( ERRFILE | PXENV_STATUS_FAILURE | 0x18000000 )
+
+/** Illegal byte sequence */
+#define EILSEQ ( ERRFILE | PXENV_STATUS_FAILURE | 0x19000000 )
+
+/** Operation in progress */
+#define EINPROGRESS ( ERRFILE | PXENV_STATUS_FAILURE | 0x1a000000 )
+
+/** Interrupted function call */
+#define EINTR ( ERRFILE | PXENV_STATUS_FAILURE | 0x1b000000 )
+
+/** Invalid argument */
+#define EINVAL ( ERRFILE | PXENV_STATUS_BAD_FUNC | 0x1c000000 )
+
+/** Input/output error */
+#define EIO \
+ ( ERRFILE | PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION | 0x1d000000 )
+
+/** Socket is connected */
+#define EISCONN ( ERRFILE | PXENV_STATUS_UDP_OPEN | 0x1e000000 )
+
+/** Is a directory */
+#define EISDIR ( ERRFILE | PXENV_STATUS_FAILURE | 0x1f000000 )
+
+/** Too many levels of symbolic links */
+#define ELOOP ( ERRFILE | PXENV_STATUS_FAILURE | 0x20000000 )
+
+/** Too many open files */
+#define EMFILE ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x21000000 )
+
+/** Too many links */
+#define EMLINK ( ERRFILE | PXENV_STATUS_FAILURE | 0x22000000 )
+
+/** Inappropriate message buffer length */
+#define EMSGSIZE ( ERRFILE | PXENV_STATUS_BAD_FUNC | 0x23000000 )
+
+/** Reserved */
+#define EMULTIHOP ( ERRFILE | PXENV_STATUS_FAILURE | 0x24000000 )
+
+/** Filename too long */
+#define ENAMETOOLONG ( ERRFILE | PXENV_STATUS_FAILURE | 0x25000000 )
+
+/** Network is down */
+#define ENETDOWN ( ERRFILE | PXENV_STATUS_ARP_TIMEOUT | 0x26000000 )
+
+/** Connection aborted by network */
+#define ENETRESET ( ERRFILE | PXENV_STATUS_FAILURE | 0x27000000 )
+
+/** Network unreachable */
+#define ENETUNREACH ( ERRFILE | PXENV_STATUS_ARP_TIMEOUT | 0x28000000 )
+
+/** Too many open files in system */
+#define ENFILE ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x29000000 )
+
+/** No buffer space available */
+#define ENOBUFS ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x2a000000 )
+
+/** No message is available on the STREAM head read queue */
+#define ENODATA ( ERRFILE | PXENV_STATUS_FAILURE | 0x2b000000 )
+
+/** No such device */
+#define ENODEV ( ERRFILE | PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x2c000000 )
+
+/** No such file or directory */
+#define ENOENT ( ERRFILE | PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x2d000000 )
+
+/** Exec format error */
+#define ENOEXEC ( ERRFILE | PXENV_STATUS_FAILURE | 0x2e000000 )
+
+/** No locks available */
+#define ENOLCK ( ERRFILE | PXENV_STATUS_FAILURE | 0x2f000000 )
+
+/** Reserved */
+#define ENOLINK ( ERRFILE | PXENV_STATUS_FAILURE | 0x30000000 )
+
+/** Not enough space */
+#define ENOMEM ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x31000000 )
+
+/** No message of the desired type */
+#define ENOMSG ( ERRFILE | PXENV_STATUS_FAILURE | 0x32000000 )
+
+/** Protocol not available */
+#define ENOPROTOOPT ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x33000000 )
+
+/** No space left on device */
+#define ENOSPC ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x34000000 )
+
+/** No STREAM resources */
+#define ENOSR ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x35000000 )
+
+/** Not a STREAM */
+#define ENOSTR ( ERRFILE | PXENV_STATUS_FAILURE | 0x36000000 )
+
+/** Function not implemented */
+#define ENOSYS ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x37000000 )
+
+/** The socket is not connected */
+#define ENOTCONN ( ERRFILE | PXENV_STATUS_FAILURE | 0x38000000 )
+
+/** Not a directory */
+#define ENOTDIR ( ERRFILE | PXENV_STATUS_FAILURE | 0x39000000 )
+
+/** Directory not empty */
+#define ENOTEMPTY ( ERRFILE | PXENV_STATUS_FAILURE | 0x3a000000 )
+
+/** Not a socket */
+#define ENOTSOCK ( ERRFILE | PXENV_STATUS_FAILURE | 0x3b000000 )
+
+/** Not supported */
+#define ENOTSUP ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x3c000000 )
+
+/** Inappropriate I/O control operation */
+#define ENOTTY ( ERRFILE | PXENV_STATUS_FAILURE | 0x3d000000 )
+
+/** No such device or address */
+#define ENXIO ( ERRFILE | PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x3e000000 )
+
+/** Operation not supported on socket */
+#define EOPNOTSUPP ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x3f000000 )
+
+/** Value too large to be stored in data type */
+#define EOVERFLOW ( ERRFILE | PXENV_STATUS_FAILURE | 0x40000000 )
+
+/** Operation not permitted */
+#define EPERM ( ERRFILE | PXENV_STATUS_TFTP_ACCESS_VIOLATION | 0x41000000 )
+
+/** Broken pipe */
+#define EPIPE ( ERRFILE | PXENV_STATUS_FAILURE | 0x42000000 )
+
+/** Protocol error */
+#define EPROTO ( ERRFILE | PXENV_STATUS_FAILURE | 0x43000000 )
+
+/** Protocol not supported */
+#define EPROTONOSUPPORT ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x44000000 )
+
+/** Protocol wrong type for socket */
+#define EPROTOTYPE ( ERRFILE | PXENV_STATUS_FAILURE | 0x45000000 )
+
+/** Result too large */
+#define ERANGE ( ERRFILE | PXENV_STATUS_FAILURE | 0x46000000 )
+
+/** Read-only file system */
+#define EROFS ( ERRFILE | PXENV_STATUS_FAILURE | 0x47000000 )
+
+/** Invalid seek */
+#define ESPIPE ( ERRFILE | PXENV_STATUS_FAILURE | 0x48000000 )
+
+/** No such process */
+#define ESRCH ( ERRFILE | PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x49000000 )
+
+/** Stale file handle */
+#define ESTALE ( ERRFILE | PXENV_STATUS_FAILURE | 0x4a000000 )
+
+/** STREAM ioctl() timeout */
+#define ETIME ( ERRFILE | PXENV_STATUS_FAILURE | 0x4b000000 )
+
+/** Operation timed out */
+#define ETIMEDOUT ( ERRFILE | PXENV_STATUS_TFTP_READ_TIMEOUT | 0x4c000000 )
+
+/** Text file busy */
+#define ETXTBSY ( ERRFILE | PXENV_STATUS_FAILURE | 0x4d000000 )
+
+/** Operation would block (different from EAGAIN!) */
+#define EWOULDBLOCK ( ERRFILE | PXENV_STATUS_TFTP_OPEN | 0x4e000000 )
+
+/** Improper link */
+#define EXDEV ( ERRFILE | PXENV_STATUS_FAILURE | 0x4f000000 )
+
+/** @} */
+
+/**
+ * @defgroup euniq Per-file error disambiguators
+ *
+ * Files which use the same error number multiple times should
+ * probably define their own error subspace using these
+ * disambiguators. For example:
+ *
+ * #define ETCP_HEADER_TOO_SHORT EUNIQ_01
+ * #define ETCP_BAD_CHECKSUM EUNIQ_02
+ *
+ * @{
+ */
+
+#define EUNIQ_01 0x00000100
+#define EUNIQ_02 0x00000200
+#define EUNIQ_03 0x00000300
+#define EUNIQ_04 0x00000400
+#define EUNIQ_05 0x00000500
+#define EUNIQ_06 0x00000600
+#define EUNIQ_07 0x00000700
+#define EUNIQ_08 0x00000800
+#define EUNIQ_09 0x00000900
+#define EUNIQ_0A 0x00000a00
+#define EUNIQ_0B 0x00000b00
+#define EUNIQ_0C 0x00000c00
+#define EUNIQ_0D 0x00000d00
+#define EUNIQ_0E 0x00000e00
+#define EUNIQ_0F 0x00000f00
+#define EUNIQ_10 0x00001000
+#define EUNIQ_11 0x00001100
+#define EUNIQ_12 0x00001200
+#define EUNIQ_13 0x00001300
+#define EUNIQ_14 0x00001400
+#define EUNIQ_15 0x00001500
+#define EUNIQ_16 0x00001600
+#define EUNIQ_17 0x00001700
+#define EUNIQ_18 0x00001800
+#define EUNIQ_19 0x00001900
+#define EUNIQ_1A 0x00001a00
+#define EUNIQ_1B 0x00001b00
+#define EUNIQ_1C 0x00001c00
+#define EUNIQ_1D 0x00001d00
+#define EUNIQ_1E 0x00001e00
+#define EUNIQ_1F 0x00001f00
+
+/** @} */
+
+extern int errno;
+
+#endif /* ERRNO_H */
diff --git a/gpxe/src/include/etherboot.h b/gpxe/src/include/etherboot.h
new file mode 100644
index 00000000..2a465954
--- /dev/null
+++ b/gpxe/src/include/etherboot.h
@@ -0,0 +1,42 @@
+#ifndef ETHERBOOT_H
+#define ETHERBOOT_H
+
+/*
+ * Standard includes that we always want
+ *
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <strings.h>
+#include <console.h>
+#include <gpxe/timer.h>
+#include <gpxe/if_arp.h>
+#include <gpxe/if_ether.h>
+
+typedef unsigned long Address;
+
+/*
+ * IMPORTANT!!!!!!!!!!!!!!
+ *
+ * Everything below this point is cruft left over from older versions
+ * of Etherboot. Do not add *anything* below this point. Things are
+ * gradually being moved to individual header files.
+ *
+ */
+
+/* Link configuration time in tenths of a second */
+#ifndef VALID_LINK_TIMEOUT
+#define VALID_LINK_TIMEOUT 100 /* 10.0 seconds */
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
+#endif /* ETHERBOOT_H */
diff --git a/gpxe/src/include/fs.h b/gpxe/src/include/fs.h
new file mode 100644
index 00000000..1dfe8fd9
--- /dev/null
+++ b/gpxe/src/include/fs.h
@@ -0,0 +1,41 @@
+#ifndef FS_H
+#define FS_H
+
+#include <stdint.h>
+
+//typedef uint64_t sector_t;
+
+#ifdef IDE_DISK
+int ide_probe(int drive);
+int ide_read(int drive, sector_t sector, void *buffer);
+#endif
+
+#ifdef USB_DISK
+int usb_probe(int drive);
+int usb_read(int drive, sector_t sector, void *buffer);
+#endif
+
+#define DISK_IDE 1
+#define DISK_MEM 2
+#define DISK_USB 3
+
+int devopen(const char *name, int *reopen);
+int devread(unsigned long sector, unsigned long byte_offset,
+ unsigned long byte_len, void *buf);
+
+int file_open(const char *filename);
+int file_read(void *buf, unsigned long len);
+int file_seek(unsigned long offset);
+unsigned long file_size(void);
+
+#define PARTITION_UNKNOWN 0xbad6a7
+
+#ifdef ELTORITO
+int open_eltorito_image(int part, unsigned long *start, unsigned long *length);
+#else
+# define open_eltorito_image(x,y,z) PARTITION_UNKNOWN
+#endif
+
+extern int using_devsize;
+
+#endif /* FS_H */
diff --git a/gpxe/src/include/getopt.h b/gpxe/src/include/getopt.h
new file mode 100644
index 00000000..2505223e
--- /dev/null
+++ b/gpxe/src/include/getopt.h
@@ -0,0 +1,92 @@
+#ifndef _GETOPT_H
+#define _GETOPT_H
+
+/** @file
+ *
+ * Parse command-line options
+ *
+ */
+
+#include <stddef.h>
+
+enum getopt_argument_requirement {
+ /** Option does not take an argument */
+ no_argument = 0,
+ /** Option requires an argument */
+ required_argument = 1,
+ /** Option may have an argument */
+ optional_argument = 2,
+};
+
+/** A long option, as used for getopt_long() */
+struct option {
+ /** Long name of this option */
+ const char *name;
+ /** Option takes an argument
+ *
+ * Must be one of @c no_argument, @c required_argument, or @c
+ * optional_argument.
+ */
+ int has_arg;
+ /** Location into which to store @c val, or NULL.
+ *
+ * See the description for @c val for more details.
+ */
+ int *flag;
+ /** Value to return
+ *
+ * If @c flag is NULL, then this is the value that will be
+ * returned by getopt_long() when this option is found, and
+ * should therefore be set to the equivalent short option
+ * character.
+ *
+ * If @c flag is non-NULL, then this value will be written to
+ * the location pointed to by @flag, and getopt_long() will
+ * return 0.
+ */
+ int val;
+};
+
+extern char *optarg;
+extern int optind;
+extern int nextchar;
+extern int optopt;
+
+extern int getopt_long ( int argc, char * const argv[], const char *optstring,
+ const struct option *longopts, int *longindex );
+
+/**
+ * Parse command-line options
+ *
+ * @v argv Argument count
+ * @v argv Argument list
+ * @v optstring Option specification string
+ * @ret option Option found, or -1 for no more options
+ *
+ * See getopt_long() for full details.
+ */
+static inline int getopt ( int argc, char * const argv[],
+ const char *optstring ) {
+ static const struct option no_options[] = {
+ { NULL, 0, NULL, 0 }
+ };
+ return getopt_long ( argc, argv, optstring, no_options, NULL );
+}
+
+/**
+ * Reset getopt() internal state
+ *
+ * Due to a limitation of the POSIX getopt() API, it is necessary to
+ * add a call to reset_getopt() before each set of calls to getopt()
+ * or getopt_long(). This arises because POSIX assumes that each
+ * process will parse command line arguments no more than once; this
+ * assumption is not valid within Etherboot. We work around the
+ * limitation by arranging for execv() to call reset_getopt() before
+ * executing the command.
+ */
+static inline void reset_getopt ( void ) {
+ optind = 1;
+ nextchar = 0;
+}
+
+#endif /* _GETOPT_H */
diff --git a/gpxe/src/include/gpxe/abft.h b/gpxe/src/include/gpxe/abft.h
new file mode 100644
index 00000000..1c651ef1
--- /dev/null
+++ b/gpxe/src/include/gpxe/abft.h
@@ -0,0 +1,35 @@
+#ifndef _GPXE_ABFT_H
+#define _GPXE_ABFT_H
+
+/** @file
+ *
+ * AoE boot firmware table
+ *
+ */
+
+#include <stdint.h>
+#include <gpxe/acpi.h>
+#include <gpxe/if_ether.h>
+
+/** AoE boot firmware table signature */
+#define ABFT_SIG "aBFT"
+
+/**
+ * AoE Boot Firmware Table (aBFT)
+ */
+struct abft_table {
+ /** ACPI header */
+ struct acpi_description_header acpi;
+ /** AoE shelf */
+ uint16_t shelf;
+ /** AoE slot */
+ uint8_t slot;
+ /** Reserved */
+ uint8_t reserved_a;
+ /** MAC address */
+ uint8_t mac[ETH_ALEN];
+} __attribute__ (( packed ));
+
+extern void abft_fill_data ( struct aoe_session *aoe );
+
+#endif /* _GPXE_ABFT_H */
diff --git a/gpxe/src/include/gpxe/acpi.h b/gpxe/src/include/gpxe/acpi.h
new file mode 100644
index 00000000..33b1b2b7
--- /dev/null
+++ b/gpxe/src/include/gpxe/acpi.h
@@ -0,0 +1,41 @@
+#ifndef _GPXE_ACPI_H
+#define _GPXE_ACPI_H
+
+/** @file
+ *
+ * ACPI data structures
+ *
+ */
+
+#include <stdint.h>
+
+/**
+ * An ACPI description header
+ *
+ * This is the structure common to the start of all ACPI system
+ * description tables.
+ */
+struct acpi_description_header {
+ /** ACPI signature (4 ASCII characters) */
+ char signature[4];
+ /** Length of table, in bytes, including header */
+ uint32_t length;
+ /** ACPI Specification minor version number */
+ uint8_t revision;
+ /** To make sum of entire table == 0 */
+ uint8_t checksum;
+ /** OEM identification */
+ char oem_id[6];
+ /** OEM table identification */
+ char oem_table_id[8];
+ /** OEM revision number */
+ uint32_t oem_revision;
+ /** ASL compiler vendor ID */
+ char asl_compiler_id[4];
+ /** ASL compiler revision number */
+ uint32_t asl_compiler_revision;
+} __attribute__ (( packed ));
+
+extern void acpi_fix_checksum ( struct acpi_description_header *acpi );
+
+#endif /* _GPXE_ACPI_H */
diff --git a/gpxe/src/include/gpxe/aes.h b/gpxe/src/include/gpxe/aes.h
new file mode 100644
index 00000000..75cb4c44
--- /dev/null
+++ b/gpxe/src/include/gpxe/aes.h
@@ -0,0 +1,8 @@
+#ifndef _GPXE_AES_H
+#define _GPXE_AES_H
+
+struct crypto_algorithm;
+
+extern struct crypto_algorithm aes_algorithm;
+
+#endif /* _GPXE_AES_H */
diff --git a/gpxe/src/include/gpxe/ansiesc.h b/gpxe/src/include/gpxe/ansiesc.h
new file mode 100644
index 00000000..ccc4ca65
--- /dev/null
+++ b/gpxe/src/include/gpxe/ansiesc.h
@@ -0,0 +1,118 @@
+#ifndef _GPXE_ANSIESC_H
+#define _GPXE_ANSIESC_H
+
+/** @file
+ *
+ * ANSI escape sequences
+ *
+ * ANSI X3.64 (aka ECMA-48 or ISO/IEC 6429, available from
+ * http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf)
+ * defines escape sequences consisting of:
+ *
+ * A Control Sequence Introducer (CSI)
+ *
+ * Zero or more Parameter Bytes (P)
+ *
+ * Zero or more Intermediate Bytes (I)
+ *
+ * A Final Byte (F)
+ *
+ * The CSI consists of ESC (0x1b) followed by "[" (0x5b). The
+ * Parameter Bytes, for a standardised (i.e. not private or
+ * experimental) sequence, consist of a list of ASCII decimal integers
+ * separated by semicolons. The Intermediate Bytes (in the range 0x20
+ * to 0x2f) and the Final Byte (in the range 0x40 to 0x4f) determine
+ * the control function.
+ *
+ */
+
+/** A handler for an escape sequence */
+struct ansiesc_handler {
+ /** The control function identifier
+ *
+ * The control function identifier consists of the
+ * Intermediate Bytes (if any) and the Final Byte. In
+ * practice, no more than one immediate byte is ever used, so
+ * the byte combination can be efficiently expressed as a
+ * single integer, in the obvious way (with the Final Byte
+ * being the least significant byte).
+ */
+ unsigned int function;
+ /** Handle escape sequence
+ *
+ * @v count Parameter count
+ * @v params Parameter list
+ *
+ * A negative parameter value indicates that the parameter was
+ * omitted and that the default value for this control
+ * function should be used.
+ *
+ * Since all parameters are optional, there is no way to
+ * distinguish between "zero parameters" and "single parameter
+ * omitted". Consequently, the parameter list will always
+ * contain at least one item.
+ */
+ void ( * handle ) ( unsigned int count, int params[] );
+};
+
+/** Maximum number of parameters within a single escape sequence */
+#define ANSIESC_MAX_PARAMS 4
+
+/**
+ * ANSI escape sequence context
+ *
+ * This provides temporary storage for processing escape sequences,
+ * and points to the list of escape sequence handlers.
+ */
+struct ansiesc_context {
+ /** Array of handlers
+ *
+ * Must be terminated by a handler with @c function set to
+ * zero.
+ */
+ struct ansiesc_handler *handlers;
+ /** Parameter count
+ *
+ * Will be zero when not currently in an escape sequence.
+ */
+ unsigned int count;
+ /** Parameter list */
+ int params[ANSIESC_MAX_PARAMS];
+ /** Control function identifier */
+ unsigned int function;
+};
+
+/** Escape character */
+#define ESC 0x1b
+
+/** Control Sequence Introducer */
+#define CSI "\033["
+
+/**
+ * @defgroup ansifuncs ANSI escape sequence function identifiers
+ * @{
+ */
+
+/** Cursor position */
+#define ANSIESC_CUP 'H'
+
+/** Erase in page */
+#define ANSIESC_ED 'J'
+
+/** Erase from cursor to end of page */
+#define ANSIESC_ED_TO_END 0
+
+/** Erase from start of page to cursor */
+#define ANSIESC_ED_FROM_START 1
+
+/** Erase whole page */
+#define ANSIESC_ED_ALL 2
+
+/** Select graphic rendition */
+#define ANSIESC_SGR 'm'
+
+/** @} */
+
+extern int ansiesc_process ( struct ansiesc_context *ctx, int c );
+
+#endif /* _GPXE_ANSIESC_H */
diff --git a/gpxe/src/include/gpxe/aoe.h b/gpxe/src/include/gpxe/aoe.h
new file mode 100644
index 00000000..85683384
--- /dev/null
+++ b/gpxe/src/include/gpxe/aoe.h
@@ -0,0 +1,126 @@
+#ifndef _GPXE_AOE_H
+#define _GPXE_AOE_H
+
+/** @file
+ *
+ * AoE protocol
+ *
+ */
+
+#include <stdint.h>
+#include <gpxe/list.h>
+#include <gpxe/if_ether.h>
+#include <gpxe/retry.h>
+#include <gpxe/async.h>
+#include <gpxe/ata.h>
+
+/** An AoE ATA command */
+struct aoecmd {
+ /** AoE command flags */
+ uint8_t aflags;
+ /** ATA error/feature register */
+ uint8_t err_feat;
+ /** ATA sector count register */
+ uint8_t count;
+ /** ATA command/status register */
+ uint8_t cmd_stat;
+ /** Logical block address, in little-endian order */
+ union {
+ uint64_t u64;
+ uint8_t bytes[6];
+ } lba;
+ /** Data payload */
+ uint8_t data[0];
+} __attribute__ (( packed ));
+
+#define AOE_FL_EXTENDED 0x40 /**< LBA48 extended addressing */
+#define AOE_FL_DEV_HEAD 0x10 /**< Device/head flag */
+#define AOE_FL_ASYNC 0x02 /**< Asynchronous write */
+#define AOE_FL_WRITE 0x01 /**< Write command */
+
+/** An AoE header */
+struct aoehdr {
+ /** Protocol version number and flags */
+ uint8_t ver_flags;
+ /** Error code */
+ uint8_t error;
+ /** Major device number, in network byte order */
+ uint16_t major;
+ /** Minor device number */
+ uint8_t minor;
+ /** Command number */
+ uint8_t command;
+ /** Tag, in network byte order */
+ uint32_t tag;
+ /** Payload */
+ union {
+ /** ATA command */
+ struct aoecmd command[0];
+ } arg;
+} __attribute__ (( packed ));
+
+#define AOE_VERSION 0x10 /**< Version 1 */
+#define AOE_VERSION_MASK 0xf0 /**< Version part of ver_flags field */
+
+#define AOE_FL_RESPONSE 0x08 /**< Message is a response */
+#define AOE_FL_ERROR 0x04 /**< Command generated an error */
+
+#define AOE_MAJOR_BROADCAST 0xffff
+#define AOE_MINOR_BROADCAST 0xff
+
+#define AOE_CMD_ATA 0x00 /**< Issue ATA command */
+#define AOE_CMD_CONFIG 0x01 /**< Query Config Information */
+
+#define AOE_TAG_MAGIC 0xebeb0000
+
+#define AOE_ERR_BAD_COMMAND 1 /**< Unrecognised command code */
+#define AOE_ERR_BAD_PARAMETER 2 /**< Bad argument parameter */
+#define AOE_ERR_UNAVAILABLE 3 /**< Device unavailable */
+#define AOE_ERR_CONFIG_EXISTS 4 /**< Config string present */
+#define AOE_ERR_BAD_VERSION 5 /**< Unsupported version */
+
+/** An AoE session */
+struct aoe_session {
+ /** Reference counter */
+ struct refcnt refcnt;
+
+ /** List of all AoE sessions */
+ struct list_head list;
+
+ /** Network device */
+ struct net_device *netdev;
+
+ /** Major number */
+ uint16_t major;
+ /** Minor number */
+ uint8_t minor;
+ /** Target MAC address */
+ uint8_t target[ETH_ALEN];
+
+ /** Tag for current AoE command */
+ uint32_t tag;
+
+ /** Current ATA command */
+ struct ata_command *command;
+ /** Overall status of current ATA command */
+ unsigned int status;
+ /** Byte offset within command's data buffer */
+ unsigned int command_offset;
+ /** Return status code for command */
+ int rc;
+
+ /** Retransmission timer */
+ struct retry_timer timer;
+};
+
+#define AOE_STATUS_ERR_MASK 0x0f /**< Error portion of status code */
+#define AOE_STATUS_PENDING 0x80 /**< Command pending */
+
+/** Maximum number of sectors per packet */
+#define AOE_MAX_COUNT 2
+
+extern void aoe_detach ( struct ata_device *ata );
+extern int aoe_attach ( struct ata_device *ata, struct net_device *netdev,
+ const char *root_path );
+
+#endif /* _GPXE_AOE_H */
diff --git a/gpxe/src/include/gpxe/arp.h b/gpxe/src/include/gpxe/arp.h
new file mode 100644
index 00000000..6464ce0c
--- /dev/null
+++ b/gpxe/src/include/gpxe/arp.h
@@ -0,0 +1,41 @@
+#ifndef _GPXE_ARP_H
+#define _GPXE_ARP_H
+
+/** @file
+ *
+ * Address Resolution Protocol
+ *
+ */
+
+#include <gpxe/tables.h>
+
+struct net_device;
+struct net_protocol;
+
+/** A network-layer protocol that relies upon ARP */
+struct arp_net_protocol {
+ /** Network-layer protocol */
+ struct net_protocol *net_protocol;
+ /** Check existence of address
+ *
+ * @v netdev Network device
+ * @v net_addr Network-layer address
+ * @ret rc Return status code
+ */
+ int ( * check ) ( struct net_device *netdev,
+ const void *net_addr );
+};
+
+/** Declare an ARP protocol */
+#define __arp_net_protocol \
+ __table ( struct arp_net_protocol, arp_net_protocols, 01 )
+
+extern struct net_protocol arp_protocol;
+
+extern int arp_resolve ( struct net_device *netdev,
+ struct net_protocol *net_protocol,
+ const void *dest_net_addr,
+ const void *source_net_addr,
+ void *dest_ll_addr );
+
+#endif /* _GPXE_ARP_H */
diff --git a/gpxe/src/include/gpxe/asn1.h b/gpxe/src/include/gpxe/asn1.h
new file mode 100644
index 00000000..1ad90050
--- /dev/null
+++ b/gpxe/src/include/gpxe/asn1.h
@@ -0,0 +1,32 @@
+#ifndef _GPXE_ASN1_H
+#define _GPXE_ASN1_H
+
+/** @file
+ *
+ * ASN.1 encoding
+ *
+ */
+
+#define ASN1_INTEGER 0x02
+#define ASN1_BIT_STRING 0x03
+#define ASN1_OCTET_STRING 0x04
+#define ASN1_NULL 0x05
+#define ASN1_OID 0x06
+#define ASN1_SEQUENCE 0x30
+#define ASN1_IP_ADDRESS 0x40
+#define ASN1_EXPLICIT_TAG 0xa0
+
+/**
+ * A DER-encoded ASN.1 object cursor
+ */
+struct asn1_cursor {
+ /** Start of data */
+ uint8_t *data;
+ /** Length of data */
+ size_t len;
+};
+
+extern int asn1_enter_object ( struct asn1_cursor *cursor, unsigned int type );
+extern int asn1_skip_object ( struct asn1_cursor *cursor, unsigned int type );
+
+#endif /* _GPXE_ASN1_H */
diff --git a/gpxe/src/include/gpxe/async.h b/gpxe/src/include/gpxe/async.h
new file mode 100644
index 00000000..2d1d31a4
--- /dev/null
+++ b/gpxe/src/include/gpxe/async.h
@@ -0,0 +1,228 @@
+#ifndef _GPXE_ASYNC_H
+#define _GPXE_ASYNC_H
+
+/** @file
+ *
+ * Asynchronous operations
+ *
+ */
+
+#include <gpxe/list.h>
+
+struct async;
+
+/** An asynchronous operation ID
+ *
+ * Only positive identifiers are valid; negative values are used to
+ * indicate errors.
+ */
+typedef long aid_t;
+
+/** Signals that can be delivered to asynchronous operations */
+enum signal {
+ /** A child asynchronous operation has completed
+ *
+ * The parent should call async_wait() to reap the completed
+ * child. async_wait() will return the exit status and
+ * operation identifier of the child.
+ *
+ * The handler for this signal can be set to @c NULL; if it
+ * is, then the children will accumulate as zombies until
+ * async_wait() is called.
+ *
+ * The handler for this signal can also be set to @c SIG_IGN;
+ * if it is, then the children will automatically be reaped.
+ * Note that if you use @c SIG_IGN then you will not be able
+ * to retrieve the return status of the children; the call to
+ * async_wait() will simply return -ECHILD.
+ */
+ SIGCHLD = 0,
+ /** Cancel asynchronous operation
+ *
+ * This signal should trigger the asynchronous operation to
+ * cancel itself (including killing all its own children, if
+ * any), and then call async_done(). The asynchronous
+ * operation is allowed to not complete immediately.
+ *
+ * The handler for this signal can be set to @c NULL; if it
+ * is, then attempts to cancel the asynchronous operation will
+ * fail and the operation will complete normally. Anything
+ * waiting for the operation to cancel will block.
+ */
+ SIGKILL,
+ /** Update progress of asynchronous operation
+ *
+ * This signal should cause the asynchronous operation to
+ * immediately update the @c completed and @c total fields.
+ *
+ * The handler for this signal can be set to @c NULL; if it
+ * is, then the asynchronous operation is expected to keep its
+ * @c completed and @c total fields up to date at all times.
+ */
+ SIGUPDATE,
+ SIGMAX
+};
+
+/**
+ * A signal handler
+ *
+ * @v async Asynchronous operation
+ * @v signal Signal received
+ */
+typedef void ( * signal_handler_t ) ( struct async *async,
+ enum signal signal );
+
+/** Asynchronous operation operations */
+struct async_operations {
+ /** Reap asynchronous operation
+ *
+ * @v async Asynchronous operation
+ *
+ * Release all resources associated with the asynchronous
+ * operation. This will be called only after the asynchronous
+ * operation itself calls async_done(), so the only remaining
+ * resources will probably be the memory used by the struct
+ * async itself.
+ *
+ * This method can be set to @c NULL; if it is, then no
+ * resources will be freed. This may be suitable for
+ * asynchronous operations that consume no dynamically
+ * allocated memory.
+ */
+ void ( * reap ) ( struct async *async );
+ /** Handle signals */
+ signal_handler_t signal[SIGMAX];
+};
+
+/** An asynchronous operation */
+struct async {
+ /** Other asynchronous operations with the same parent */
+ struct list_head siblings;
+ /** Child asynchronous operations */
+ struct list_head children;
+ /** Parent asynchronous operation
+ *
+ * This field is optional; if left to NULL then the owner must
+ * never call async_done().
+ */
+ struct async *parent;
+ /** Asynchronous operation ID */
+ aid_t aid;
+ /** Final return status code */
+ int rc;
+
+ /** Amount of operation completed so far
+ *
+ * The units for this quantity are arbitrary. @c completed
+ * divded by @total should give something which approximately
+ * represents the progress through the operation. For a
+ * download operation, using byte counts would make sense.
+ *
+ * This progress indicator should also incorporate the status
+ * of any child asynchronous operations.
+ */
+ unsigned long completed;
+ /** Total operation size
+ *
+ * See @c completed. A zero value means "total size unknown"
+ * and is explcitly permitted; users should take this into
+ * account before calculating @c completed/total.
+ */
+ unsigned long total;
+
+ struct async_operations *aop;
+};
+
+extern struct async_operations default_async_operations;
+extern struct async_operations orphan_async_operations;
+
+extern aid_t async_init ( struct async *async, struct async_operations *aop,
+ struct async *parent );
+extern void async_uninit ( struct async *async );
+extern void async_ignore_signal ( struct async *async, enum signal signal );
+extern void async_signal ( struct async *async, enum signal signal );
+extern void async_signal_children ( struct async *async, enum signal signal );
+extern void async_done ( struct async *async, int rc );
+extern aid_t async_wait ( struct async *async, int *rc, int block );
+
+/** Default signal handler */
+#define SIG_DFL NULL
+
+/** Ignore signal */
+#define SIG_IGN async_ignore_signal
+
+/**
+ * Initialise orphan asynchronous operation
+ *
+ * @v async Asynchronous operation
+ * @ret aid Asynchronous operation ID
+ *
+ * An orphan asynchronous operation can act as a context for child
+ * operations. However, you must not call async_done() on such an
+ * operation, since this would attempt to send a signal to its
+ * (non-existent) parent. Instead, simply free the structure (after
+ * calling async_wait() to ensure that any child operations have
+ * completed).
+ */
+static inline aid_t async_init_orphan ( struct async *async ) {
+ return async_init ( async, &orphan_async_operations, NULL );
+}
+
+/**
+ * Execute and block on an asynchronous operation
+ *
+ * @v async_temp Temporary asynchronous operation structure to use
+ * @v START Code used to start the asynchronous operation
+ * @ret rc Return status code
+ *
+ * This is a notational shorthand for writing
+ *
+ * async_init_orphan ( &async_temp );
+ * if ( ( rc = START ) == 0 )
+ * async_wait ( &async_temp );
+ * if ( rc != 0 ) {
+ * ...handle failure...
+ * }
+ *
+ * and allows you instead to write
+ *
+ * if ( ( rc = async_block ( &async_temp, START ) ) != 0 ) {
+ * ...handle failure...
+ * }
+ *
+ * The argument START is a code snippet; it should initiate an
+ * asynchronous operation as a child of @c async_temp and return an
+ * error status code if it failed to do so (e.g. due to malloc()
+ * failure).
+ */
+#define async_block( async_temp, START ) ( { \
+ int rc; \
+ \
+ async_init_orphan ( async_temp ); \
+ if ( ( rc = START ) == 0 ) \
+ async_wait ( async_temp, &rc, 1 ); \
+ rc; \
+ } )
+
+/**
+ * Execute and block on an asynchronous operation, with progress indicator
+ *
+ * @v async_temp Temporary asynchronous operation structure to use
+ * @v START Code used to start the asynchronous operation
+ * @ret rc Return status code
+ *
+ * As for async_block(), the argument START is a code snippet; it
+ * should initiate an asynchronous operation as a child of @c
+ * async_temp and return an error status code if it failed to do so
+ * (e.g. due to malloc() failure).
+ */
+#define async_block_progress( async_temp, START ) ( { \
+ int rc; \
+ \
+ async_init_orphan ( async_temp ); \
+ if ( ( rc = START ) == 0 ) \
+ async_wait_progress ( async_temp, &rc );\
+ rc; \
+ } )
+
+#endif /* _GPXE_ASYNC_H */
diff --git a/gpxe/src/include/gpxe/ata.h b/gpxe/src/include/gpxe/ata.h
new file mode 100644
index 00000000..b6da3930
--- /dev/null
+++ b/gpxe/src/include/gpxe/ata.h
@@ -0,0 +1,205 @@
+#ifndef _GPXE_ATA_H
+#define _GPXE_ATA_H
+
+#include <stdint.h>
+#include <gpxe/blockdev.h>
+#include <gpxe/uaccess.h>
+#include <gpxe/refcnt.h>
+
+/** @file
+ *
+ * ATA devices
+ *
+ */
+
+/**
+ * An ATA Logical Block Address
+ *
+ * ATA controllers have three byte-wide registers for specifying the
+ * block address: LBA Low, LBA Mid and LBA High. This allows for a
+ * 24-bit address. Some devices support the "48-bit address feature
+ * set" (LBA48), in which case each of these byte-wide registers is
+ * actually a two-entry FIFO, and the "previous" byte pushed into the
+ * FIFO is used as the corresponding high-order byte. So, to set up
+ * the 48-bit address 0x123456abcdef, you would issue
+ *
+ * 0x56 -> LBA Low register
+ * 0xef -> LBA Low register
+ * 0x34 -> LBA Mid register
+ * 0xcd -> LBA Mid register
+ * 0x12 -> LBA High register
+ * 0xab -> LBA High register
+ *
+ * This structure encapsulates this information by providing a single
+ * 64-bit integer in native byte order, unioned with bytes named so
+ * that the sequence becomes
+ *
+ * low_prev -> LBA Low register
+ * low_cur -> LBA Low register
+ * mid_prev -> LBA Mid register
+ * mid_cur -> LBA Mid register
+ * high_prev -> LBA High register
+ * high_cur -> LBA High register
+ *
+ * Just to complicate matters further, in non-LBA48 mode it is
+ * possible to have a 28-bit address, in which case bits 27:24 must be
+ * written into the low four bits of the Device register.
+ */
+union ata_lba {
+ /** LBA as a 64-bit integer in native-endian order */
+ uint64_t native;
+ /** ATA registers */
+ struct {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ uint8_t low_cur;
+ uint8_t mid_cur;
+ uint8_t high_cur;
+ uint8_t low_prev;
+ uint8_t mid_prev;
+ uint8_t high_prev;
+ uint16_t pad;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ uint16_t pad;
+ uint8_t high_prev;
+ uint8_t mid_prev;
+ uint8_t low_prev;
+ uint8_t high_cur;
+ uint8_t mid_cur;
+ uint8_t low_cur;
+#else
+#error "I need a byte order"
+#endif
+ } bytes;
+};
+
+/** An ATA 2-byte FIFO register */
+union ata_fifo {
+ /** Value in native-endian order */
+ uint16_t native;
+ /** ATA registers */
+ struct {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ uint8_t cur;
+ uint8_t prev;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ uint8_t prev;
+ uint8_t cur;
+#else
+#error "I need a byte order"
+#endif
+ } bytes;
+};
+
+/** ATA command block */
+struct ata_cb {
+ /** Logical block address */
+ union ata_lba lba;
+ /** Sector count */
+ union ata_fifo count;
+ /** Error/feature register */
+ union ata_fifo err_feat;
+ /** Device register */
+ uint8_t device;
+ /** Command/status register */
+ uint8_t cmd_stat;
+ /** LBA48 addressing flag */
+ int lba48;
+};
+
+/** Obsolete bits in the ATA device register */
+#define ATA_DEV_OBSOLETE 0xa0
+
+/** LBA flag in the ATA device register */
+#define ATA_DEV_LBA 0x40
+
+/** Slave ("device 1") flag in the ATA device register */
+#define ATA_DEV_SLAVE 0x10
+
+/** Master ("device 0") flag in the ATA device register */
+#define ATA_DEV_MASTER 0x00
+
+/** Mask of non-LBA portion of device register */
+#define ATA_DEV_MASK 0xf0
+
+/** "Read sectors" command */
+#define ATA_CMD_READ 0x20
+
+/** "Read sectors (ext)" command */
+#define ATA_CMD_READ_EXT 0x24
+
+/** "Write sectors" command */
+#define ATA_CMD_WRITE 0x30
+
+/** "Write sectors (ext)" command */
+#define ATA_CMD_WRITE_EXT 0x34
+
+/** "Identify" command */
+#define ATA_CMD_IDENTIFY 0xec
+
+/** An ATA command */
+struct ata_command {
+ /** ATA command block */
+ struct ata_cb cb;
+ /** Data-out buffer (may be NULL)
+ *
+ * If non-NULL, this buffer must be ata_command::cb::count
+ * sectors in size.
+ */
+ userptr_t data_out;
+ /** Data-in buffer (may be NULL)
+ *
+ * If non-NULL, this buffer must be ata_command::cb::count
+ * sectors in size.
+ */
+ userptr_t data_in;
+};
+
+/**
+ * Structure returned by ATA IDENTIFY command
+ *
+ * This is a huge structure with many fields that we don't care about,
+ * so we implement only a few fields.
+ */
+struct ata_identity {
+ uint16_t ignore_a[60]; /* words 0-59 */
+ uint32_t lba_sectors; /* words 60-61 */
+ uint16_t ignore_b[21]; /* words 62-82 */
+ uint16_t supports_lba48; /* word 83 */
+ uint16_t ignore_c[16]; /* words 84-99 */
+ uint64_t lba48_sectors; /* words 100-103 */
+ uint16_t ignore_d[152]; /* words 104-255 */
+};
+
+/** Supports LBA48 flag */
+#define ATA_SUPPORTS_LBA48 ( 1 << 10 )
+
+/** ATA sector size */
+#define ATA_SECTOR_SIZE 512
+
+/** An ATA device */
+struct ata_device {
+ /** Block device interface */
+ struct block_device blockdev;
+ /** Device number
+ *
+ * Must be ATA_DEV_MASTER or ATA_DEV_SLAVE.
+ */
+ int device;
+ /** LBA48 extended addressing */
+ int lba48;
+ /**
+ * Issue ATA command
+ *
+ * @v ata ATA device
+ * @v command ATA command
+ * @ret rc Return status code
+ */
+ int ( * command ) ( struct ata_device *ata,
+ struct ata_command *command );
+ /** Backing device */
+ struct refcnt *backend;
+};
+
+extern int init_atadev ( struct ata_device *ata );
+
+#endif /* _GPXE_ATA_H */
diff --git a/gpxe/src/include/gpxe/bitbash.h b/gpxe/src/include/gpxe/bitbash.h
new file mode 100644
index 00000000..62bdce00
--- /dev/null
+++ b/gpxe/src/include/gpxe/bitbash.h
@@ -0,0 +1,50 @@
+#ifndef _GPXE_BITBASH_H
+#define _GPXE_BITBASH_H
+
+/** @file
+ *
+ * Bit-bashing interfaces
+ *
+ */
+
+struct bit_basher;
+
+/** Bit-bashing operations */
+struct bit_basher_operations {
+ /**
+ * Set/clear output bit
+ *
+ * @v basher Bit-bashing interface
+ * @v bit_id Bit number
+ * @v data Value to write
+ *
+ * @c data will be 0 if a logic 0 should be written (i.e. the
+ * bit should be cleared), or -1UL if a logic 1 should be
+ * written (i.e. the bit should be set). This is done so that
+ * the method may simply binary-AND @c data with the
+ * appropriate bit mask.
+ */
+ void ( * write ) ( struct bit_basher *basher, unsigned int bit_id,
+ unsigned long data );
+ /**
+ * Read input bit
+ *
+ * @v basher Bit-bashing interface
+ * @v bit_id Bit number
+ * @ret zero Input is a logic 0
+ * @ret non-zero Input is a logic 1
+ */
+ int ( * read ) ( struct bit_basher *basher, unsigned int bit_id );
+};
+
+/** A bit-bashing interface */
+struct bit_basher {
+ /** Bit-bashing operations */
+ struct bit_basher_operations *op;
+};
+
+extern void write_bit ( struct bit_basher *basher, unsigned int bit_id,
+ unsigned long data );
+extern int read_bit ( struct bit_basher *basher, unsigned int bit_id );
+
+#endif /* _GPXE_BITBASH_H */
diff --git a/gpxe/src/include/gpxe/bitmap.h b/gpxe/src/include/gpxe/bitmap.h
new file mode 100644
index 00000000..0c2f53c8
--- /dev/null
+++ b/gpxe/src/include/gpxe/bitmap.h
@@ -0,0 +1,83 @@
+#ifndef _GPXE_BITMAP_H
+#define _GPXE_BITMAP_H
+
+/** @file
+ *
+ * Bitmaps for multicast downloads
+ *
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+/** A single block of bits within a bitmap */
+typedef unsigned long bitmap_block_t;
+
+/** Size of a block of bits (in bits) */
+#define BITMAP_BLKSIZE ( sizeof ( bitmap_block_t ) * 8 )
+
+/**
+ * Block index within bitmap
+ *
+ * @v bit Bit index
+ * @ret index Block index
+ */
+#define BITMAP_INDEX( bit ) ( (bit) / BITMAP_BLKSIZE )
+
+/**
+ * Block mask within bitmap
+ *
+ * @v bit Bit index
+ * @ret mask Block mask
+ */
+#define BITMAP_MASK( bit ) ( 1 << ( (bit) % BITMAP_BLKSIZE ) )
+
+/** A bitmap */
+struct bitmap {
+ /** Bitmap data */
+ bitmap_block_t *blocks;
+ /** Length of the bitmap, in bits */
+ unsigned int length;
+ /** Index of first gap in the bitmap */
+ unsigned int first_gap;
+};
+
+extern int bitmap_resize ( struct bitmap *bitmap, unsigned int new_length );
+extern int bitmap_test ( struct bitmap *bitmap, unsigned int bit );
+extern void bitmap_set ( struct bitmap *bitmap, unsigned int bit );
+
+/**
+ * Free bitmap resources
+ *
+ * @v bitmap Bitmap
+ */
+static inline void bitmap_free ( struct bitmap *bitmap ) {
+ free ( bitmap->blocks );
+}
+
+/**
+ * Get first gap within bitmap
+ *
+ * @v bitmap Bitmap
+ * @ret first_gap First gap
+ *
+ * The first gap is the first unset bit within the bitmap.
+ */
+static inline unsigned int bitmap_first_gap ( struct bitmap *bitmap ) {
+ return bitmap->first_gap;
+}
+
+/**
+ * Check to see if bitmap is full
+ *
+ * @v bitmap Bitmap
+ * @ret is_full Bitmap is full
+ *
+ * The bitmap is full if it has no gaps (i.e. no unset bits).
+ */
+static inline int bitmap_full ( struct bitmap *bitmap ) {
+ return ( bitmap->first_gap == bitmap->length );
+}
+
+#endif /* _GPXE_BITMAP_H */
diff --git a/gpxe/src/include/gpxe/bitops.h b/gpxe/src/include/gpxe/bitops.h
new file mode 100644
index 00000000..f95af7d3
--- /dev/null
+++ b/gpxe/src/include/gpxe/bitops.h
@@ -0,0 +1,27 @@
+#ifndef _GPXE_BITOPS_H
+#define _GPXE_BITOPS_H
+
+/** @file
+ *
+ * Bit operations
+ */
+
+#include <stdint.h>
+
+static inline uint32_t rol32 ( uint32_t data, unsigned int rotation ) {
+ return ( ( data << rotation ) | ( data >> ( 32 - rotation ) ) );
+}
+
+static inline uint32_t ror32 ( uint32_t data, unsigned int rotation ) {
+ return ( ( data >> rotation ) | ( data << ( 32 - rotation ) ) );
+}
+
+static inline uint64_t rol64 ( uint64_t data, unsigned int rotation ) {
+ return ( ( data << rotation ) | ( data >> ( 64 - rotation ) ) );
+}
+
+static inline uint64_t ror64 ( uint64_t data, unsigned int rotation ) {
+ return ( ( data >> rotation ) | ( data << ( 64 - rotation ) ) );
+}
+
+#endif /* _GPXE_BITOPS_H */
diff --git a/gpxe/src/include/gpxe/blockdev.h b/gpxe/src/include/gpxe/blockdev.h
new file mode 100644
index 00000000..467ed1d9
--- /dev/null
+++ b/gpxe/src/include/gpxe/blockdev.h
@@ -0,0 +1,43 @@
+#ifndef _GPXE_BLOCKDEV_H
+#define _GPXE_BLOCKDEV_H
+
+/**
+ * @file
+ *
+ * Block devices
+ *
+ */
+
+#include <gpxe/uaccess.h>
+
+/** A block device */
+struct block_device {
+ /** Block size */
+ size_t blksize;
+ /** Total number of blocks */
+ uint64_t blocks;
+ /**
+ * Read block
+ *
+ * @v blockdev Block device
+ * @v block Block number
+ * @v count Block count
+ * @v buffer Data buffer
+ * @ret rc Return status code
+ */
+ int ( * read ) ( struct block_device *blockdev, uint64_t block,
+ unsigned long count, userptr_t buffer );
+ /**
+ * Write block
+ *
+ * @v blockdev Block device
+ * @v block Block number
+ * @v count Block count
+ * @v buffer Data buffer
+ * @ret rc Return status code
+ */
+ int ( * write ) ( struct block_device *blockdev, uint64_t block,
+ unsigned long count, userptr_t buffer );
+};
+
+#endif /* _GPXE_BLOCKDEV_H */
diff --git a/gpxe/src/include/gpxe/chap.h b/gpxe/src/include/gpxe/chap.h
new file mode 100644
index 00000000..0ea7ac5c
--- /dev/null
+++ b/gpxe/src/include/gpxe/chap.h
@@ -0,0 +1,51 @@
+#ifndef _GPXE_CHAP_H
+#define _GPXE_CHAP_H
+
+/** @file
+ *
+ * CHAP protocol
+ *
+ */
+
+#include <stdint.h>
+#include <gpxe/md5.h>
+
+struct crypto_algorithm;
+
+/** A CHAP challenge/response */
+struct chap_challenge {
+ /** Digest algorithm used for the response */
+ struct crypto_algorithm *digest;
+ /** Context used by the digest algorithm */
+ uint8_t *digest_context;
+ /** CHAP response */
+ uint8_t *response;
+ /** Length of CHAP response */
+ size_t response_len;
+};
+
+extern int chap_init ( struct chap_challenge *chap,
+ struct crypto_algorithm *digest );
+extern void chap_update ( struct chap_challenge *chap, const void *data,
+ size_t len );
+extern void chap_respond ( struct chap_challenge *chap );
+extern void chap_finish ( struct chap_challenge *chap );
+
+/**
+ * Add identifier data to the CHAP challenge
+ *
+ * @v chap CHAP challenge/response
+ * @v identifier CHAP identifier
+ *
+ * The CHAP identifier is the first byte of the CHAP challenge. This
+ * function is a notational convenience for calling chap_update() for
+ * the identifier byte.
+ */
+static inline void chap_set_identifier ( struct chap_challenge *chap,
+ unsigned int identifier ) {
+ uint8_t ident_byte = identifier;
+
+ chap_update ( chap, &ident_byte, sizeof ( ident_byte ) );
+}
+
+#endif /* _GPXE_CHAP_H */
diff --git a/gpxe/src/include/gpxe/command.h b/gpxe/src/include/gpxe/command.h
new file mode 100644
index 00000000..5d8057ab
--- /dev/null
+++ b/gpxe/src/include/gpxe/command.h
@@ -0,0 +1,22 @@
+#ifndef _GPXE_COMMAND_H
+#define _GPXE_COMMAND_H
+
+#include <gpxe/tables.h>
+
+/** A command-line command */
+struct command {
+ /** Name of the command */
+ const char *name;
+ /**
+ * Function implementing the command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+ int ( * exec ) ( int argc, char **argv );
+};
+
+#define __command __table ( struct command, commands, 01 )
+
+#endif /* _GPXE_COMMAND_H */
diff --git a/gpxe/src/include/gpxe/cpio.h b/gpxe/src/include/gpxe/cpio.h
new file mode 100644
index 00000000..ba6f844a
--- /dev/null
+++ b/gpxe/src/include/gpxe/cpio.h
@@ -0,0 +1,51 @@
+#ifndef _GPXE_CPIO_H
+#define _GPXE_CPIO_H
+
+/** @file
+ *
+ * CPIO archives
+ *
+ */
+
+/** A CPIO archive header
+ *
+ * All field are hexadecimal ASCII numbers padded with '0' on the
+ * left to the full width of the field.
+ */
+struct cpio_header {
+ /** The string "070701" or "070702" */
+ char c_magic[6];
+ /** File inode number */
+ char c_ino[8];
+ /** File mode and permissions */
+ char c_mode[8];
+ /** File uid */
+ char c_uid[8];
+ /** File gid */
+ char c_gid[8];
+ /** Number of links */
+ char c_nlink[8];
+ /** Modification time */
+ char c_mtime[8];
+ /** Size of data field */
+ char c_filesize[8];
+ /** Major part of file device number */
+ char c_maj[8];
+ /** Minor part of file device number */
+ char c_min[8];
+ /** Major part of device node reference */
+ char c_rmaj[8];
+ /** Minor part of device node reference */
+ char c_rmin[8];
+ /** Length of filename, including final NUL */
+ char c_namesize[8];
+ /** Checksum of data field if c_magic is 070702, othersize zero */
+ char c_chksum[8];
+} __attribute__ (( packed ));
+
+/** CPIO magic */
+#define CPIO_MAGIC "070701"
+
+extern void cpio_set_field ( char *field, unsigned long value );
+
+#endif /* _GPXE_CPIO_H */
diff --git a/gpxe/src/include/gpxe/crypto.h b/gpxe/src/include/gpxe/crypto.h
new file mode 100644
index 00000000..95665acc
--- /dev/null
+++ b/gpxe/src/include/gpxe/crypto.h
@@ -0,0 +1,116 @@
+#ifndef _GPXE_CRYPTO_H
+#define _GPXE_CRYPTO_H
+
+/** @file
+ *
+ * Cryptographic API
+ *
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+
+/** A cryptographic algorithm */
+struct crypto_algorithm {
+ /** Algorithm name */
+ const char *name;
+ /** Context size */
+ size_t ctxsize;
+ /** Block size */
+ size_t blocksize;
+ /** Final output size */
+ size_t digestsize;
+ /** Initialise algorithm
+ *
+ * @v ctx Context
+ */
+ void ( * init ) ( void *ctx );
+ /** Set key
+ *
+ * @v ctx Context
+ * @v key Key
+ * @v keylen Key length
+ * @ret rc Return status code
+ */
+ int ( * setkey ) ( void *ctx, const void *key, size_t keylen );
+ /** Set initialisation vector
+ *
+ * @v ctx Context
+ * @v iv Initialisation vector
+ */
+ void ( *setiv ) ( void *ctx, const void *iv );
+ /** Encode data
+ *
+ * @v ctx Context
+ * @v src Data to encode
+ * @v dst Encoded data, or NULL
+ * @v len Length of data
+ * @ret rc Return status code
+ *
+ * For a cipher algorithm, the enciphered data should be
+ * placed in @c dst. For a digest algorithm, only the digest
+ * state should be updated, and @c dst will be NULL.
+ *
+ * @v len is guaranteed to be a multiple of @c blocksize.
+ */
+ void ( * encode ) ( void *ctx, const void *src, void *dst,
+ size_t len );
+ /** Decode data
+ *
+ * @v ctx Context
+ * @v src Data to decode
+ * @v dst Decoded data
+ * @v len Length of data
+ * @ret rc Return status code
+ *
+ * @v len is guaranteed to be a multiple of @c blocksize.
+ */
+ void ( * decode ) ( void *ctx, const void *src, void *dst,
+ size_t len );
+ /** Finalise algorithm
+ *
+ * @v ctx Context
+ * @v out Algorithm final output
+ */
+ void ( * final ) ( void *ctx, void *out );
+};
+
+static inline void digest_init ( struct crypto_algorithm *crypto,
+ void *ctx ) {
+ crypto->init ( ctx );
+}
+
+static inline void digest_update ( struct crypto_algorithm *crypto,
+ void *ctx, const void *data, size_t len ) {
+ crypto->encode ( ctx, data, NULL, len );
+}
+
+static inline void digest_final ( struct crypto_algorithm *crypto,
+ void *ctx, void *out ) {
+ crypto->final ( ctx, out );
+}
+
+static inline void cipher_setiv ( struct crypto_algorithm *crypto,
+ void *ctx, const void *iv ) {
+ crypto->setiv ( ctx, iv );
+}
+
+static inline int cipher_setkey ( struct crypto_algorithm *crypto,
+ void *ctx, const void *key, size_t keylen ) {
+ return crypto->setkey ( ctx, key, keylen );
+}
+
+static inline int is_stream_cipher ( struct crypto_algorithm *crypto ) {
+ return ( crypto->blocksize == 1 );
+}
+
+extern struct crypto_algorithm crypto_null;
+
+extern int cipher_encrypt ( struct crypto_algorithm *crypto,
+ void *ctx, const void *src, void *dst,
+ size_t len );
+extern int cipher_decrypt ( struct crypto_algorithm *crypto,
+ void *ctx, const void *src, void *dst,
+ size_t len );
+
+#endif /* _GPXE_CRYPTO_H */
diff --git a/gpxe/src/include/gpxe/device.h b/gpxe/src/include/gpxe/device.h
new file mode 100644
index 00000000..caabdae5
--- /dev/null
+++ b/gpxe/src/include/gpxe/device.h
@@ -0,0 +1,111 @@
+#ifndef _GPXE_DEVICE_H
+#define _GPXE_DEVICE_H
+
+/**
+ * @file
+ *
+ * Device model
+ *
+ */
+
+#include <gpxe/list.h>
+#include <gpxe/tables.h>
+
+/** A hardware device description */
+struct device_description {
+ /** Bus type
+ *
+ * This must be a BUS_TYPE_XXX constant.
+ */
+ unsigned int bus_type;
+ /** Location
+ *
+ * The interpretation of this field is bus-type-specific.
+ */
+ unsigned int location;
+ /** Vendor ID */
+ unsigned int vendor;
+ /** Device ID */
+ unsigned int device;
+ /** Device class */
+ unsigned long class;
+ /** I/O address */
+ unsigned long ioaddr;
+ /** IRQ */
+ unsigned int irq;
+};
+
+/** PCI bus type */
+#define BUS_TYPE_PCI 1
+
+/** ISAPnP bus type */
+#define BUS_TYPE_ISAPNP 2
+
+/** EISA bus type */
+#define BUS_TYPE_EISA 3
+
+/** MCA bus type */
+#define BUS_TYPE_MCA 4
+
+/** ISA bus type */
+#define BUS_TYPE_ISA 5
+
+/** A hardware device */
+struct device {
+ /** Name */
+ char name[16];
+ /** Device description */
+ struct device_description desc;
+ /** Devices on the same bus */
+ struct list_head siblings;
+ /** Devices attached to this device */
+ struct list_head children;
+ /** Bus device */
+ struct device *parent;
+};
+
+/**
+ * A root device
+ *
+ * Root devices are system buses such as PCI, EISA, etc.
+ *
+ */
+struct root_device {
+ /** Device chain
+ *
+ * A root device has a NULL parent field.
+ */
+ struct device dev;
+ /** Root device driver */
+ struct root_driver *driver;
+};
+
+/** A root device driver */
+struct root_driver {
+ /**
+ * Add root device
+ *
+ * @v rootdev Root device
+ * @ret rc Return status code
+ *
+ * Called from probe_devices() for all root devices in the build.
+ */
+ int ( * probe ) ( struct root_device *rootdev );
+ /**
+ * Remove root device
+ *
+ * @v rootdev Root device
+ *
+ * Called from remove_device() for all successfully-probed
+ * root devices.
+ */
+ void ( * remove ) ( struct root_device *rootdev );
+};
+
+/** Declare a root device */
+#define __root_device __table ( struct root_device, root_devices, 01 )
+
+extern int probe_devices ( void );
+extern void remove_devices ( void );
+
+#endif /* _GPXE_DEVICE_H */
diff --git a/gpxe/src/include/gpxe/dhcp.h b/gpxe/src/include/gpxe/dhcp.h
new file mode 100644
index 00000000..94cc2010
--- /dev/null
+++ b/gpxe/src/include/gpxe/dhcp.h
@@ -0,0 +1,455 @@
+#ifndef _GPXE_DHCP_H
+#define _GPXE_DHCP_H
+
+/** @file
+ *
+ * Dynamic Host Configuration Protocol
+ *
+ */
+
+#include <stdint.h>
+#include <gpxe/in.h>
+#include <gpxe/list.h>
+#include <gpxe/refcnt.h>
+#include <gpxe/tables.h>
+
+struct net_device;
+struct job_interface;
+struct dhcp_options;
+struct dhcp_packet;
+
+/** BOOTP/DHCP server port */
+#define BOOTPS_PORT 67
+
+/** BOOTP/DHCP client port */
+#define BOOTPC_PORT 68
+
+/** Construct a tag value for an encapsulated option
+ *
+ * This tag value can be passed to Etherboot functions when searching
+ * for DHCP options in order to search for a tag within an
+ * encapsulated options block.
+ */
+#define DHCP_ENCAP_OPT( encapsulator, encapsulated ) \
+ ( ( (encapsulator) << 8 ) | (encapsulated) )
+/** Extract encapsulating option block tag from encapsulated tag value */
+#define DHCP_ENCAPSULATOR( encap_opt ) ( (encap_opt) >> 8 )
+/** Extract encapsulated option tag from encapsulated tag value */
+#define DHCP_ENCAPSULATED( encap_opt ) ( (encap_opt) & 0xff )
+/** Option is encapsulated */
+#define DHCP_IS_ENCAP_OPT( opt ) DHCP_ENCAPSULATOR( opt )
+
+/**
+ * @defgroup dhcpopts DHCP option tags
+ * @{
+ */
+
+/** Padding
+ *
+ * This tag does not have a length field; it is always only a single
+ * byte in length.
+ */
+#define DHCP_PAD 0
+
+/** Minimum normal DHCP option */
+#define DHCP_MIN_OPTION 1
+
+/** Subnet mask */
+#define DHCP_SUBNET_MASK 1
+
+/** Routers */
+#define DHCP_ROUTERS 3
+
+/** DNS servers */
+#define DHCP_DNS_SERVERS 6
+
+/** Syslog servers */
+#define DHCP_LOG_SERVERS 7
+
+/** Host name */
+#define DHCP_HOST_NAME 12
+
+/** Domain name */
+#define DHCP_DOMAIN_NAME 15
+
+/** Root path */
+#define DHCP_ROOT_PATH 17
+
+/** Vendor encapsulated options */
+#define DHCP_VENDOR_ENCAP 43
+
+/** Requested IP address */
+#define DHCP_REQUESTED_ADDRESS 50
+
+/** Lease time */
+#define DHCP_LEASE_TIME 51
+
+/** Option overloading
+ *
+ * The value of this option is the bitwise-OR of zero or more
+ * DHCP_OPTION_OVERLOAD_XXX constants.
+ */
+#define DHCP_OPTION_OVERLOAD 52
+
+/** The "file" field is overloaded to contain extra DHCP options */
+#define DHCP_OPTION_OVERLOAD_FILE 1
+
+/** The "sname" field is overloaded to contain extra DHCP options */
+#define DHCP_OPTION_OVERLOAD_SNAME 2
+
+/** DHCP message type */
+#define DHCP_MESSAGE_TYPE 53
+#define DHCPDISCOVER 1
+#define DHCPOFFER 2
+#define DHCPREQUEST 3
+#define DHCPDECLINE 4
+#define DHCPACK 5
+#define DHCPNAK 6
+#define DHCPRELEASE 7
+#define DHCPINFORM 8
+
+/** DHCP server identifier */
+#define DHCP_SERVER_IDENTIFIER 54
+
+/** Parameter request list */
+#define DHCP_PARAMETER_REQUEST_LIST 55
+
+/** Maximum DHCP message size */
+#define DHCP_MAX_MESSAGE_SIZE 57
+
+/** Vendor class identifier */
+#define DHCP_VENDOR_CLASS_ID 60
+
+/** Client identifier */
+#define DHCP_CLIENT_ID 61
+
+/** TFTP server name
+ *
+ * This option replaces the fixed "sname" field, when that field is
+ * used to contain overloaded options.
+ */
+#define DHCP_TFTP_SERVER_NAME 66
+
+/** Bootfile name
+ *
+ * This option replaces the fixed "file" field, when that field is
+ * used to contain overloaded options.
+ */
+#define DHCP_BOOTFILE_NAME 67
+
+/** Client system architecture */
+#define DHCP_CLIENT_ARCHITECTURE 93
+
+/** Client network device interface */
+#define DHCP_CLIENT_NDI 94
+
+/** UUID client identifier */
+#define DHCP_CLIENT_UUID 97
+
+/** Etherboot-specific encapsulated options
+ *
+ * This encapsulated options field is used to contain all options
+ * specific to Etherboot (i.e. not assigned by IANA or other standards
+ * bodies).
+ */
+#define DHCP_EB_ENCAP 175
+
+/** Priority of this options block
+ *
+ * This is a signed 8-bit integer field indicating the priority of
+ * this block of options. It can be used to specify the relative
+ * priority of multiple option blocks (e.g. options from non-volatile
+ * storage versus options from a DHCP server).
+ */
+#define DHCP_EB_PRIORITY DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 1 )
+
+/** "Your" IP address
+ *
+ * This option is used internally to contain the value of the "yiaddr"
+ * field, in order to provide a consistent approach to storing and
+ * processing options. It should never be present in a DHCP packet.
+ */
+#define DHCP_EB_YIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 2 )
+
+/** "Server" IP address
+ *
+ * This option is used internally to contain the value of the "siaddr"
+ * field, in order to provide a consistent approach to storing and
+ * processing options. It should never be present in a DHCP packet.
+ */
+#define DHCP_EB_SIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 3 )
+
+/*
+ * Tags in the range 0x10-0x7f are reserved for feature markers
+ *
+ */
+
+/** Ignore ProxyDHCP
+ *
+ * If set to a non-zero value, gPXE will not wait for ProxyDHCP offers
+ * and will ignore any ProxyDHCP offers that it receives.
+ */
+#define DHCP_EB_NO_PROXYDHCP DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xb0 )
+
+/** Network device descriptor
+ *
+ * Byte 0 is the bus type ID; remaining bytes depend on the bus type.
+ *
+ * PCI devices:
+ * Byte 0 : 1 (PCI)
+ * Byte 1 : PCI vendor ID MSB
+ * Byte 2 : PCI vendor ID LSB
+ * Byte 3 : PCI device ID MSB
+ * Byte 4 : PCI device ID LSB
+ */
+#define DHCP_EB_BUS_ID DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xb1 )
+
+/** BIOS drive number
+ *
+ * This is the drive number for a drive emulated via INT 13. 0x80 is
+ * the first hard disk, 0x81 is the second hard disk, etc.
+ */
+#define DHCP_EB_BIOS_DRIVE DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xbd )
+
+/** Username
+ *
+ * This will be used as the username for any required authentication.
+ * It is expected that this option's value will be held in
+ * non-volatile storage, rather than transmitted as part of a DHCP
+ * packet.
+ */
+#define DHCP_EB_USERNAME DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xbe )
+
+/** Password
+ *
+ * This will be used as the password for any required authentication.
+ * It is expected that this option's value will be held in
+ * non-volatile storage, rather than transmitted as part of a DHCP
+ * packet.
+ */
+#define DHCP_EB_PASSWORD DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xbf )
+
+/** iSCSI primary target IQN */
+#define DHCP_ISCSI_PRIMARY_TARGET_IQN 201
+
+/** iSCSI secondary target IQN */
+#define DHCP_ISCSI_SECONDARY_TARGET_IQN 202
+
+/** iSCSI initiator IQN */
+#define DHCP_ISCSI_INITIATOR_IQN 203
+
+/** Maximum normal DHCP option */
+#define DHCP_MAX_OPTION 254
+
+/** End of options
+ *
+ * This tag does not have a length field; it is always only a single
+ * byte in length.
+ */
+#define DHCP_END 255
+
+/** @} */
+
+/**
+ * Count number of arguments to a variadic macro
+ *
+ * This rather neat, non-iterative solution is courtesy of Laurent
+ * Deniau.
+ *
+ */
+#define _VA_ARG_COUNT( _1, _2, _3, _4, _5, _6, _7, _8, \
+ _9, _10, _11, _12, _13, _14, _15, _16, \
+ _17, _18, _19, _20, _21, _22, _23, _24, \
+ _25, _26, _27, _28, _29, _30, _31, _32, \
+ _33, _34, _35, _36, _37, _38, _39, _40, \
+ _41, _42, _43, _44, _45, _46, _47, _48, \
+ _49, _50, _51, _52, _53, _54, _55, _56, \
+ _57, _58, _59, _60, _61, _62, _63, N, ... ) N
+#define VA_ARG_COUNT( ... ) \
+ _VA_ARG_COUNT ( __VA_ARGS__, \
+ 63, 62, 61, 60, 59, 58, 57, 56, \
+ 55, 54, 53, 52, 51, 50, 49, 48, \
+ 47, 46, 45, 44, 43, 42, 41, 40, \
+ 39, 38, 37, 36, 35, 34, 33, 32, \
+ 31, 30, 29, 28, 27, 26, 25, 24, \
+ 23, 22, 21, 20, 19, 18, 17, 16, \
+ 15, 14, 13, 12, 11, 10, 9, 8, \
+ 7, 6, 5, 4, 3, 2, 1, 0 )
+
+/** Construct a DHCP option from a list of bytes */
+#define DHCP_OPTION( ... ) VA_ARG_COUNT ( __VA_ARGS__ ), __VA_ARGS__
+
+/** Construct a DHCP option from a list of characters */
+#define DHCP_STRING( ... ) DHCP_OPTION ( __VA_ARGS__ )
+
+/** Construct a byte-valued DHCP option */
+#define DHCP_BYTE( value ) DHCP_OPTION ( value )
+
+/** Construct a word-valued DHCP option */
+#define DHCP_WORD( value ) DHCP_OPTION ( ( ( (value) >> 8 ) & 0xff ), \
+ ( ( (value) >> 0 ) & 0xff ) )
+
+/** Construct a dword-valued DHCP option */
+#define DHCP_DWORD( value ) DHCP_OPTION ( ( ( (value) >> 24 ) & 0xff ), \
+ ( ( (value) >> 16 ) & 0xff ), \
+ ( ( (value) >> 8 ) & 0xff ), \
+ ( ( (value) >> 0 ) & 0xff ) )
+
+/** Construct a DHCP encapsulated options field */
+#define DHCP_ENCAP( ... ) DHCP_OPTION ( __VA_ARGS__, DHCP_END )
+
+/**
+ * A DHCP option
+ *
+ * DHCP options consist of a mandatory tag, a length field that is
+ * mandatory for all options except @c DHCP_PAD and @c DHCP_END, and a
+ * payload.
+ */
+struct dhcp_option {
+ /** Tag
+ *
+ * Must be a @c DHCP_XXX value.
+ */
+ uint8_t tag;
+ /** Length
+ *
+ * This is the length of the data field (i.e. excluding the
+ * tag and length fields). For the two tags @c DHCP_PAD and
+ * @c DHCP_END, the length field is implicitly zero and is
+ * also missing, i.e. these DHCP options are only a single
+ * byte in length.
+ */
+ uint8_t len;
+ /** Option data */
+ uint8_t data[0];
+} __attribute__ (( packed ));
+
+/**
+ * Length of a DHCP option header
+ *
+ * The header is the portion excluding the data, i.e. the tag and the
+ * length.
+ */
+#define DHCP_OPTION_HEADER_LEN ( offsetof ( struct dhcp_option, data ) )
+
+/** Maximum length for a single DHCP option */
+#define DHCP_MAX_LEN 0xff
+
+/**
+ * A DHCP header
+ *
+ */
+struct dhcphdr {
+ /** Operation
+ *
+ * This must be either @c BOOTP_REQUEST or @c BOOTP_REPLY.
+ */
+ uint8_t op;
+ /** Hardware address type
+ *
+ * This is an ARPHRD_XXX constant. Note that ARPHRD_XXX
+ * constants are nominally 16 bits wide; this could be
+ * considered to be a bug in the BOOTP/DHCP specification.
+ */
+ uint8_t htype;
+ /** Hardware address length */
+ uint8_t hlen;
+ /** Number of hops from server */
+ uint8_t hops;
+ /** Transaction ID */
+ uint32_t xid;
+ /** Seconds since start of acquisition */
+ uint16_t secs;
+ /** Flags */
+ uint16_t flags;
+ /** "Client" IP address
+ *
+ * This is filled in if the client already has an IP address
+ * assigned and can respond to ARP requests.
+ */
+ struct in_addr ciaddr;
+ /** "Your" IP address
+ *
+ * This is the IP address assigned by the server to the client.
+ */
+ struct in_addr yiaddr;
+ /** "Server" IP address
+ *
+ * This is the IP address of the next server to be used in the
+ * boot process.
+ */
+ struct in_addr siaddr;
+ /** "Gateway" IP address
+ *
+ * This is the IP address of the DHCP relay agent, if any.
+ */
+ struct in_addr giaddr;
+ /** Client hardware address */
+ uint8_t chaddr[16];
+ /** Server host name (null terminated)
+ *
+ * This field may be overridden and contain DHCP options
+ */
+ char sname[64];
+ /** Boot file name (null terminated)
+ *
+ * This field may be overridden and contain DHCP options
+ */
+ char file[128];
+ /** DHCP magic cookie
+ *
+ * Must have the value @c DHCP_MAGIC_COOKIE.
+ */
+ uint32_t magic;
+ /** DHCP options
+ *
+ * Variable length; extends to the end of the packet. Minimum
+ * length (for the sake of sanity) is 1, to allow for a single
+ * @c DHCP_END tag.
+ */
+ uint8_t options[0];
+};
+
+/** Opcode for a request from client to server */
+#define BOOTP_REQUEST 1
+
+/** Opcode for a reply from server to client */
+#define BOOTP_REPLY 2
+
+/** BOOTP reply must be broadcast
+ *
+ * Clients that cannot accept unicast BOOTP replies must set this
+ * flag.
+ */
+#define BOOTP_FL_BROADCAST 0x8000
+
+/** DHCP magic cookie */
+#define DHCP_MAGIC_COOKIE 0x63825363UL
+
+/** DHCP minimum packet length
+ *
+ * This is the mandated minimum packet length that a DHCP participant
+ * must be prepared to receive.
+ */
+#define DHCP_MIN_LEN 552
+
+/** Maximum time that we will wait for ProxyDHCP offers */
+#define PROXYDHCP_WAIT_TIME ( TICKS_PER_SEC * 1 )
+
+/** Settings block name used for DHCP responses */
+#define DHCP_SETTINGS_NAME "dhcp"
+
+/** Settings block name used for ProxyDHCP responses */
+#define PROXYDHCP_SETTINGS_NAME "proxydhcp"
+
+extern int create_dhcp_packet ( struct dhcp_packet *dhcppkt,
+ struct net_device *netdev, uint8_t msgtype,
+ struct dhcp_options *options,
+ void *data, size_t max_len );
+extern int create_dhcp_request ( struct dhcp_packet *dhcppkt,
+ struct net_device *netdev,
+ struct dhcp_packet *dhcpoffer,
+ void *data, size_t max_len );
+extern int start_dhcp ( struct job_interface *job, struct net_device *netdev );
+
+#endif /* _GPXE_DHCP_H */
diff --git a/gpxe/src/include/gpxe/dhcpopts.h b/gpxe/src/include/gpxe/dhcpopts.h
new file mode 100644
index 00000000..8391a9d4
--- /dev/null
+++ b/gpxe/src/include/gpxe/dhcpopts.h
@@ -0,0 +1,32 @@
+#ifndef _GPXE_DHCPOPTS_H
+#define _GPXE_DHCPOPTS_H
+
+/** @file
+ *
+ * DHCP options
+ *
+ */
+
+#include <stdint.h>
+
+/** A DHCP options block */
+struct dhcp_options {
+ /** Option block raw data */
+ void *data;
+ /** Option block length */
+ size_t len;
+ /** Option block maximum length */
+ size_t max_len;
+};
+
+extern int dhcpopt_store ( struct dhcp_options *options, unsigned int tag,
+ const void *data, size_t len );
+extern int dhcpopt_extensible_store ( struct dhcp_options *options,
+ unsigned int tag,
+ const void *data, size_t len );
+extern int dhcpopt_fetch ( struct dhcp_options *options, unsigned int tag,
+ void *data, size_t len );
+extern void dhcpopt_init ( struct dhcp_options *options,
+ void *data, size_t max_len );
+
+#endif /* _GPXE_DHCPOPTS_H */
diff --git a/gpxe/src/include/gpxe/dhcppkt.h b/gpxe/src/include/gpxe/dhcppkt.h
new file mode 100644
index 00000000..179be2f8
--- /dev/null
+++ b/gpxe/src/include/gpxe/dhcppkt.h
@@ -0,0 +1,35 @@
+#ifndef _GPXE_DHCPPKT_H
+#define _GPXE_DHCPPKT_H
+
+/** @file
+ *
+ * DHCP packets
+ *
+ */
+
+#include <gpxe/dhcp.h>
+#include <gpxe/dhcpopts.h>
+
+/**
+ * A DHCP packet
+ *
+ */
+struct dhcp_packet {
+ /** The DHCP packet contents */
+ struct dhcphdr *dhcphdr;
+ /** Maximum length of the DHCP packet buffer */
+ size_t max_len;
+ /** Used length of the DHCP packet buffer */
+ size_t len;
+ /** DHCP option blocks */
+ struct dhcp_options options;
+};
+
+extern int dhcppkt_store ( struct dhcp_packet *dhcppkt, unsigned int tag,
+ const void *data, size_t len );
+extern int dhcppkt_fetch ( struct dhcp_packet *dhcppkt, unsigned int tag,
+ void *data, size_t len );
+extern void dhcppkt_init ( struct dhcp_packet *dhcppkt,
+ void *data, size_t len );
+
+#endif /* _GPXE_DHCPPKT_H */
diff --git a/gpxe/src/include/gpxe/dns.h b/gpxe/src/include/gpxe/dns.h
new file mode 100644
index 00000000..3e3cff1b
--- /dev/null
+++ b/gpxe/src/include/gpxe/dns.h
@@ -0,0 +1,90 @@
+#ifndef _GPXE_DNS_H
+#define _GPXE_DNS_H
+
+/** @file
+ *
+ * DNS protocol
+ *
+ */
+
+#include <stdint.h>
+#include <gpxe/in.h>
+
+/*
+ * Constants
+ *
+ */
+
+#define DNS_TYPE_A 1
+#define DNS_TYPE_CNAME 5
+#define DNS_TYPE_ANY 255
+
+#define DNS_CLASS_IN 1
+#define DNS_CLASS_CS 2
+#define DNS_CLASS_CH 3
+#define DNS_CLASS_HS 4
+
+#define DNS_FLAG_QUERY ( 0x00 << 15 )
+#define DNS_FLAG_RESPONSE ( 0x01 << 15 )
+#define DNS_FLAG_QR(flags) ( (flags) & ( 0x01 << 15 ) )
+#define DNS_FLAG_OPCODE_QUERY ( 0x00 << 11 )
+#define DNS_FLAG_OPCODE_IQUERY ( 0x01 << 11 )
+#define DNS_FLAG_OPCODE_STATUS ( 0x02 << 11 )
+#define DNS_FLAG_OPCODE(flags) ( (flags) & ( 0x0f << 11 ) )
+#define DNS_FLAG_RD ( 0x01 << 8 )
+#define DNS_FLAG_RA ( 0x01 << 7 )
+#define DNS_FLAG_RCODE_OK ( 0x00 << 0 )
+#define DNS_FLAG_RCODE_NX ( 0x03 << 0 )
+#define DNS_FLAG_RCODE(flags) ( (flags) & ( 0x0f << 0 ) )
+
+#define DNS_PORT 53
+#define DNS_MAX_RETRIES 3
+#define DNS_MAX_CNAME_RECURSION 0x30
+
+/*
+ * DNS protocol structures
+ *
+ */
+struct dns_header {
+ uint16_t id;
+ uint16_t flags;
+ uint16_t qdcount;
+ uint16_t ancount;
+ uint16_t nscount;
+ uint16_t arcount;
+} __attribute__ (( packed ));
+
+struct dns_query_info {
+ uint16_t qtype;
+ uint16_t qclass;
+} __attribute__ (( packed ));
+
+struct dns_query {
+ struct dns_header dns;
+ char payload[ 256 + sizeof ( struct dns_query_info ) ];
+} __attribute__ (( packed ));
+
+struct dns_rr_info_common {
+ uint16_t type;
+ uint16_t class;
+ uint32_t ttl;
+ uint16_t rdlength;
+} __attribute__ (( packed ));
+
+struct dns_rr_info_a {
+ struct dns_rr_info_common common;
+ struct in_addr in_addr;
+} __attribute__ (( packed ));
+
+struct dns_rr_info_cname {
+ struct dns_rr_info_common common;
+ char cname[0];
+} __attribute__ (( packed ));
+
+union dns_rr_info {
+ struct dns_rr_info_common common;
+ struct dns_rr_info_a a;
+ struct dns_rr_info_cname cname;
+};
+
+#endif /* _GPXE_DNS_H */
diff --git a/gpxe/src/include/gpxe/downloader.h b/gpxe/src/include/gpxe/downloader.h
new file mode 100644
index 00000000..33aa7692
--- /dev/null
+++ b/gpxe/src/include/gpxe/downloader.h
@@ -0,0 +1,17 @@
+#ifndef _GPXE_DOWNLOADER_H
+#define _GPXE_DOWNLOADER_H
+
+/** @file
+ *
+ * Image downloader
+ *
+ */
+
+struct job_interface;
+struct image;
+
+extern int create_downloader ( struct job_interface *job, struct image *image,
+ int ( * register_image ) ( struct image *image ),
+ int type, ... );
+
+#endif /* _GPXE_DOWNLOADER_H */
diff --git a/gpxe/src/include/gpxe/editbox.h b/gpxe/src/include/gpxe/editbox.h
new file mode 100644
index 00000000..47b07c25
--- /dev/null
+++ b/gpxe/src/include/gpxe/editbox.h
@@ -0,0 +1,51 @@
+#ifndef _GPXE_EDITBOX_H
+#define _GPXE_EDITBOX_H
+
+/** @file
+ *
+ * Editable text box widget
+ *
+ */
+
+#include <curses.h>
+#include <gpxe/editstring.h>
+
+/** An editable text box widget */
+struct edit_box {
+ /** Editable string */
+ struct edit_string string;
+ /** Containing window */
+ WINDOW *win;
+ /** Row */
+ unsigned int row;
+ /** Starting column */
+ unsigned int col;
+ /** Width */
+ unsigned int width;
+ /** First displayed character */
+ unsigned int first;
+};
+
+extern void init_editbox ( struct edit_box *box, char *buf, size_t len,
+ WINDOW *win, unsigned int row, unsigned int col,
+ unsigned int width )
+ __attribute__ (( nonnull (1, 2) ));
+extern void draw_editbox ( struct edit_box *box ) __nonnull;
+static inline int __pure edit_editbox ( struct edit_box *box, int key ) __nonnull;
+
+/**
+ * Edit text box widget
+ *
+ * @v box Editable text box widget
+ * @v key Key pressed by user
+ * @ret key Key returned to application, or zero
+ *
+ * You must call draw_editbox() to update the display after calling
+ * edit_editbox().
+ *
+ */
+static inline int edit_editbox ( struct edit_box *box, int key ) {
+ return edit_string ( &box->string, key );
+}
+
+#endif /* _GPXE_EDITBOX_H */
diff --git a/gpxe/src/include/gpxe/editstring.h b/gpxe/src/include/gpxe/editstring.h
new file mode 100644
index 00000000..fad8bd5a
--- /dev/null
+++ b/gpxe/src/include/gpxe/editstring.h
@@ -0,0 +1,31 @@
+#ifndef _GPXE_EDITSTRING_H
+#define _GPXE_EDITSTRING_H
+
+/** @file
+ *
+ * Editable strings
+ *
+ */
+
+/** An editable string */
+struct edit_string {
+ /** Buffer for string */
+ char *buf;
+ /** Size of buffer (including terminating NUL) */
+ size_t len;
+ /** Cursor position */
+ unsigned int cursor;
+
+ /* The following items are the edit history */
+
+ /** Last cursor position */
+ unsigned int last_cursor;
+ /** Start of modified portion of string */
+ unsigned int mod_start;
+ /** End of modified portion of string */
+ unsigned int mod_end;
+};
+
+extern int edit_string ( struct edit_string *string, int key ) __nonnull;
+
+#endif /* _GPXE_EDITSTRING_H */
diff --git a/gpxe/src/include/gpxe/eisa.h b/gpxe/src/include/gpxe/eisa.h
new file mode 100644
index 00000000..e9d890e1
--- /dev/null
+++ b/gpxe/src/include/gpxe/eisa.h
@@ -0,0 +1,125 @@
+#ifndef EISA_H
+#define EISA_H
+
+#include <stdint.h>
+#include <gpxe/isa_ids.h>
+#include <gpxe/device.h>
+#include <gpxe/tables.h>
+
+/*
+ * EISA constants
+ *
+ */
+
+#define EISA_MIN_SLOT (0x1)
+#define EISA_MAX_SLOT (0xf) /* Must be 2^n - 1 */
+#define EISA_SLOT_BASE( n ) ( 0x1000 * (n) )
+
+#define EISA_VENDOR_ID ( 0xc80 )
+#define EISA_PROD_ID ( 0xc82 )
+#define EISA_GLOBAL_CONFIG ( 0xc84 )
+
+#define EISA_CMD_RESET ( 1 << 2 )
+#define EISA_CMD_ENABLE ( 1 << 0 )
+
+/** An EISA device ID list entry */
+struct eisa_device_id {
+ /** Name */
+ const char *name;
+ /** Manufacturer ID */
+ uint16_t vendor_id;
+ /** Product ID */
+ uint16_t prod_id;
+};
+
+/** An EISA device */
+struct eisa_device {
+ /** Generic device */
+ struct device dev;
+ /** Slot number */
+ unsigned int slot;
+ /** I/O address */
+ uint16_t ioaddr;
+ /** Manufacturer ID */
+ uint16_t vendor_id;
+ /** Product ID */
+ uint16_t prod_id;
+ /** Driver for this device */
+ struct eisa_driver *driver;
+ /** Driver-private data
+ *
+ * Use eisa_set_drvdata() and eisa_get_drvdata() to access
+ * this field.
+ */
+ void *priv;
+ /** Driver name */
+ const char *driver_name;
+};
+
+/** An EISA driver */
+struct eisa_driver {
+ /** EISA ID table */
+ struct eisa_device_id *ids;
+ /** Number of entries in EISA ID table */
+ unsigned int id_count;
+ /**
+ * Probe device
+ *
+ * @v eisa EISA device
+ * @v id Matching entry in ID table
+ * @ret rc Return status code
+ */
+ int ( * probe ) ( struct eisa_device *eisa,
+ const struct eisa_device_id *id );
+ /**
+ * Remove device
+ *
+ * @v eisa EISA device
+ */
+ void ( * remove ) ( struct eisa_device *eisa );
+};
+
+/** Declare an EISA driver */
+#define __eisa_driver __table ( struct eisa_driver, eisa_drivers, 01 )
+
+extern void eisa_device_enabled ( struct eisa_device *eisa, int enabled );
+
+/**
+ * Enable EISA device
+ *
+ * @v eisa EISA device
+ */
+static inline void enable_eisa_device ( struct eisa_device *eisa ) {
+ eisa_device_enabled ( eisa, 1 );
+}
+
+/**
+ * Disable EISA device
+ *
+ * @v eisa EISA device
+ */
+static inline void disable_eisa_device ( struct eisa_device *eisa ) {
+ eisa_device_enabled ( eisa, 0 );
+}
+
+/**
+ * Set EISA driver-private data
+ *
+ * @v eisa EISA device
+ * @v priv Private data
+ */
+static inline void eisa_set_drvdata ( struct eisa_device *eisa, void *priv ) {
+ eisa->priv = priv;
+}
+
+/**
+ * Get EISA driver-private data
+ *
+ * @v eisa EISA device
+ * @ret priv Private data
+ */
+static inline void * eisa_get_drvdata ( struct eisa_device *eisa ) {
+ return eisa->priv;
+}
+
+#endif /* EISA_H */
diff --git a/gpxe/src/include/gpxe/elf.h b/gpxe/src/include/gpxe/elf.h
new file mode 100644
index 00000000..db28a60a
--- /dev/null
+++ b/gpxe/src/include/gpxe/elf.h
@@ -0,0 +1,15 @@
+#ifndef _GPXE_ELF_H
+#define _GPXE_ELF_H
+
+/**
+ * @file
+ *
+ * ELF image format
+ *
+ */
+
+#include <elf.h>
+
+extern int elf_load ( struct image *image );
+
+#endif /* _GPXE_ELF_H */
diff --git a/gpxe/src/include/gpxe/embedded.h b/gpxe/src/include/gpxe/embedded.h
new file mode 100644
index 00000000..ec457055
--- /dev/null
+++ b/gpxe/src/include/gpxe/embedded.h
@@ -0,0 +1,9 @@
+#ifndef _GPXE_EMBEDDED_H
+#define _GPXE_EMBEDDED_H
+
+#include <gpxe/image.h>
+
+struct image *embedded_image(void);
+
+#endif
+
diff --git a/gpxe/src/include/gpxe/errfile.h b/gpxe/src/include/gpxe/errfile.h
new file mode 100644
index 00000000..ae8b1480
--- /dev/null
+++ b/gpxe/src/include/gpxe/errfile.h
@@ -0,0 +1,157 @@
+#ifndef _GPXE_ERRFILE_H
+#define _GPXE_ERRFILE_H
+
+/** @file
+ *
+ * Error file identifiers
+ *
+ */
+
+#include <bits/errfile.h>
+
+/**
+ * @defgroup errfilecat Error file identifier categories
+ *
+ * @{
+ */
+
+#define ERRFILE_CORE 0x00002000 /**< Core code */
+#define ERRFILE_DRIVER 0x00004000 /**< Driver code */
+#define ERRFILE_NET 0x00006000 /**< Networking code */
+#define ERRFILE_IMAGE 0x00008000 /**< Image code */
+#define ERRFILE_OTHER 0x0000e000 /**< Any other code */
+
+/** @} */
+
+/** Flag for architecture-dependent error files */
+#define ERRFILE_ARCH 0x00800000
+
+/**
+ * @defgroup errfile Error file identifiers
+ *
+ * These values are automatically incorporated into the definitions
+ * for error numbers such as EINVAL.
+ *
+ * @{
+ */
+
+#define ERRFILE_asprintf ( ERRFILE_CORE | 0x00000000 )
+#define ERRFILE_downloader ( ERRFILE_CORE | 0x00010000 )
+#define ERRFILE_exec ( ERRFILE_CORE | 0x00020000 )
+#define ERRFILE_hw ( ERRFILE_CORE | 0x00030000 )
+#define ERRFILE_iobuf ( ERRFILE_CORE | 0x00040000 )
+#define ERRFILE_job ( ERRFILE_CORE | 0x00050000 )
+#define ERRFILE_linebuf ( ERRFILE_CORE | 0x00060000 )
+#define ERRFILE_monojob ( ERRFILE_CORE | 0x00070000 )
+#define ERRFILE_nvo ( ERRFILE_CORE | 0x00080000 )
+#define ERRFILE_open ( ERRFILE_CORE | 0x00090000 )
+#define ERRFILE_posix_io ( ERRFILE_CORE | 0x000a0000 )
+#define ERRFILE_resolv ( ERRFILE_CORE | 0x000b0000 )
+#define ERRFILE_settings ( ERRFILE_CORE | 0x000c0000 )
+#define ERRFILE_vsprintf ( ERRFILE_CORE | 0x000d0000 )
+#define ERRFILE_xfer ( ERRFILE_CORE | 0x000e0000 )
+#define ERRFILE_bitmap ( ERRFILE_CORE | 0x000f0000 )
+
+#define ERRFILE_eisa ( ERRFILE_DRIVER | 0x00000000 )
+#define ERRFILE_isa ( ERRFILE_DRIVER | 0x00010000 )
+#define ERRFILE_isapnp ( ERRFILE_DRIVER | 0x00020000 )
+#define ERRFILE_mca ( ERRFILE_DRIVER | 0x00030000 )
+#define ERRFILE_pci ( ERRFILE_DRIVER | 0x00040000 )
+
+#define ERRFILE_nvs ( ERRFILE_DRIVER | 0x00100000 )
+#define ERRFILE_spi ( ERRFILE_DRIVER | 0x00110000 )
+#define ERRFILE_i2c_bit ( ERRFILE_DRIVER | 0x00120000 )
+#define ERRFILE_spi_bit ( ERRFILE_DRIVER | 0x00130000 )
+
+#define ERRFILE_3c509 ( ERRFILE_DRIVER | 0x00200000 )
+#define ERRFILE_bnx2 ( ERRFILE_DRIVER | 0x00210000 )
+#define ERRFILE_cs89x0 ( ERRFILE_DRIVER | 0x00220000 )
+#define ERRFILE_eepro ( ERRFILE_DRIVER | 0x00230000 )
+#define ERRFILE_etherfabric ( ERRFILE_DRIVER | 0x00240000 )
+#define ERRFILE_legacy ( ERRFILE_DRIVER | 0x00250000 )
+#define ERRFILE_natsemi ( ERRFILE_DRIVER | 0x00260000 )
+#define ERRFILE_pnic ( ERRFILE_DRIVER | 0x00270000 )
+#define ERRFILE_prism2_pci ( ERRFILE_DRIVER | 0x00280000 )
+#define ERRFILE_prism2_plx ( ERRFILE_DRIVER | 0x00290000 )
+#define ERRFILE_rtl8139 ( ERRFILE_DRIVER | 0x002a0000 )
+#define ERRFILE_smc9000 ( ERRFILE_DRIVER | 0x002b0000 )
+#define ERRFILE_tg3 ( ERRFILE_DRIVER | 0x002c0000 )
+#define ERRFILE_3c509_eisa ( ERRFILE_DRIVER | 0x002d0000 )
+#define ERRFILE_3c515 ( ERRFILE_DRIVER | 0x002e0000 )
+#define ERRFILE_3c529 ( ERRFILE_DRIVER | 0x002f0000 )
+#define ERRFILE_3c595 ( ERRFILE_DRIVER | 0x00300000 )
+#define ERRFILE_3c5x9 ( ERRFILE_DRIVER | 0x00310000 )
+#define ERRFILE_3c90x ( ERRFILE_DRIVER | 0x00320000 )
+#define ERRFILE_amd8111e ( ERRFILE_DRIVER | 0x00330000 )
+#define ERRFILE_davicom ( ERRFILE_DRIVER | 0x00340000 )
+#define ERRFILE_depca ( ERRFILE_DRIVER | 0x00350000 )
+#define ERRFILE_dmfe ( ERRFILE_DRIVER | 0x00360000 )
+#define ERRFILE_eepro100 ( ERRFILE_DRIVER | 0x00380000 )
+#define ERRFILE_epic100 ( ERRFILE_DRIVER | 0x00390000 )
+#define ERRFILE_forcedeth ( ERRFILE_DRIVER | 0x003a0000 )
+#define ERRFILE_mtd80x ( ERRFILE_DRIVER | 0x003b0000 )
+#define ERRFILE_ns83820 ( ERRFILE_DRIVER | 0x003c0000 )
+#define ERRFILE_ns8390 ( ERRFILE_DRIVER | 0x003d0000 )
+#define ERRFILE_pcnet32 ( ERRFILE_DRIVER | 0x003e0000 )
+#define ERRFILE_r8169 ( ERRFILE_DRIVER | 0x003f0000 )
+#define ERRFILE_sis900 ( ERRFILE_DRIVER | 0x00400000 )
+#define ERRFILE_sundance ( ERRFILE_DRIVER | 0x00410000 )
+#define ERRFILE_tlan ( ERRFILE_DRIVER | 0x00420000 )
+#define ERRFILE_tulip ( ERRFILE_DRIVER | 0x00430000 )
+#define ERRFILE_via_rhine ( ERRFILE_DRIVER | 0x00440000 )
+#define ERRFILE_via_velocity ( ERRFILE_DRIVER | 0x00450000 )
+#define ERRFILE_w89c840 ( ERRFILE_DRIVER | 0x00460000 )
+#define ERRFILE_ipoib ( ERRFILE_DRIVER | 0x00470000 )
+#define ERRFILE_e1000 ( ERRFILE_DRIVER | 0x00480000 )
+#define ERRFILE_e1000_hw ( ERRFILE_DRIVER | 0x00490000 )
+
+#define ERRFILE_scsi ( ERRFILE_DRIVER | 0x00700000 )
+#define ERRFILE_arbel ( ERRFILE_DRIVER | 0x00710000 )
+#define ERRFILE_hermon ( ERRFILE_DRIVER | 0x00720000 )
+
+#define ERRFILE_aoe ( ERRFILE_NET | 0x00000000 )
+#define ERRFILE_arp ( ERRFILE_NET | 0x00010000 )
+#define ERRFILE_dhcpopts ( ERRFILE_NET | 0x00020000 )
+#define ERRFILE_ethernet ( ERRFILE_NET | 0x00030000 )
+#define ERRFILE_icmpv6 ( ERRFILE_NET | 0x00040000 )
+#define ERRFILE_ipv4 ( ERRFILE_NET | 0x00050000 )
+#define ERRFILE_ipv6 ( ERRFILE_NET | 0x00060000 )
+#define ERRFILE_ndp ( ERRFILE_NET | 0x00070000 )
+#define ERRFILE_netdevice ( ERRFILE_NET | 0x00080000 )
+#define ERRFILE_nullnet ( ERRFILE_NET | 0x00090000 )
+#define ERRFILE_tcp ( ERRFILE_NET | 0x000a0000 )
+#define ERRFILE_ftp ( ERRFILE_NET | 0x000b0000 )
+#define ERRFILE_http ( ERRFILE_NET | 0x000c0000 )
+#define ERRFILE_iscsi ( ERRFILE_NET | 0x000d0000 )
+#define ERRFILE_tcpip ( ERRFILE_NET | 0x000e0000 )
+#define ERRFILE_udp ( ERRFILE_NET | 0x000f0000 )
+#define ERRFILE_dhcp ( ERRFILE_NET | 0x00100000 )
+#define ERRFILE_dns ( ERRFILE_NET | 0x00110000 )
+#define ERRFILE_tftp ( ERRFILE_NET | 0x00120000 )
+#define ERRFILE_infiniband ( ERRFILE_NET | 0x00130000 )
+#define ERRFILE_netdev_settings ( ERRFILE_NET | 0x00140000 )
+#define ERRFILE_dhcppkt ( ERRFILE_NET | 0x00150000 )
+
+#define ERRFILE_image ( ERRFILE_IMAGE | 0x00000000 )
+#define ERRFILE_elf ( ERRFILE_IMAGE | 0x00010000 )
+#define ERRFILE_script ( ERRFILE_IMAGE | 0x00020000 )
+#define ERRFILE_segment ( ERRFILE_IMAGE | 0x00030000 )
+
+#define ERRFILE_asn1 ( ERRFILE_OTHER | 0x00000000 )
+#define ERRFILE_chap ( ERRFILE_OTHER | 0x00010000 )
+#define ERRFILE_aoeboot ( ERRFILE_OTHER | 0x00020000 )
+#define ERRFILE_autoboot ( ERRFILE_OTHER | 0x00030000 )
+#define ERRFILE_dhcpmgmt ( ERRFILE_OTHER | 0x00040000 )
+#define ERRFILE_imgmgmt ( ERRFILE_OTHER | 0x00050000 )
+#define ERRFILE_pxe_tftp ( ERRFILE_OTHER | 0x00060000 )
+#define ERRFILE_pxe_udp ( ERRFILE_OTHER | 0x00070000 )
+#define ERRFILE_axtls_aes ( ERRFILE_OTHER | 0x00080000 )
+#define ERRFILE_cipher ( ERRFILE_OTHER | 0x00090000 )
+#define ERRFILE_image_cmd ( ERRFILE_OTHER | 0x000a0000 )
+#define ERRFILE_uri_test ( ERRFILE_OTHER | 0x000b0000 )
+#define ERRFILE_ibft ( ERRFILE_OTHER | 0x000c0000 )
+#define ERRFILE_tls ( ERRFILE_OTHER | 0x000d0000 )
+
+/** @} */
+
+#endif /* _GPXE_ERRFILE_H */
diff --git a/gpxe/src/include/gpxe/errortab.h b/gpxe/src/include/gpxe/errortab.h
new file mode 100644
index 00000000..e9a56768
--- /dev/null
+++ b/gpxe/src/include/gpxe/errortab.h
@@ -0,0 +1,19 @@
+#ifndef _GPXE_ERRORTAB_H
+#define _GPXE_ERRORTAB_H
+
+/** @file
+ *
+ * Error message tables
+ *
+ */
+
+#include <gpxe/tables.h>
+
+struct errortab {
+ int errno;
+ const char *text;
+};
+
+#define __errortab __table ( struct errortab, errortab, 01 )
+
+#endif /* _GPXE_ERRORTAB_H */
diff --git a/gpxe/src/include/gpxe/ethernet.h b/gpxe/src/include/gpxe/ethernet.h
new file mode 100644
index 00000000..158fe066
--- /dev/null
+++ b/gpxe/src/include/gpxe/ethernet.h
@@ -0,0 +1,33 @@
+#ifndef _GPXE_ETHERNET_H
+#define _GPXE_ETHERNET_H
+
+/** @file
+ *
+ * Ethernet protocol
+ *
+ */
+
+#include <stdint.h>
+#include <gpxe/netdevice.h>
+
+extern struct ll_protocol ethernet_protocol;
+
+extern const char * eth_ntoa ( const void *ll_addr );
+
+/**
+ * Allocate Ethernet device
+ *
+ * @v priv_size Size of driver private data
+ * @ret netdev Network device, or NULL
+ */
+static inline struct net_device * alloc_etherdev ( size_t priv_size ) {
+ struct net_device *netdev;
+
+ netdev = alloc_netdev ( priv_size );
+ if ( netdev ) {
+ netdev->ll_protocol = &ethernet_protocol;
+ }
+ return netdev;
+}
+
+#endif /* _GPXE_ETHERNET_H */
diff --git a/gpxe/src/include/gpxe/fakedhcp.h b/gpxe/src/include/gpxe/fakedhcp.h
new file mode 100644
index 00000000..990b56af
--- /dev/null
+++ b/gpxe/src/include/gpxe/fakedhcp.h
@@ -0,0 +1,21 @@
+#ifndef _GPXE_FAKEDHCP_H
+#define _GPXE_FAKEDHCP_H
+
+/** @file
+ *
+ * Fake DHCP packets
+ *
+ */
+
+#include <stdint.h>
+
+struct net_device;
+
+extern int create_fakedhcpdiscover ( struct net_device *netdev,
+ void *data, size_t max_len );
+extern int create_fakedhcpack ( struct net_device *netdev,
+ void *data, size_t max_len );
+extern int create_fakeproxydhcpack ( struct net_device *netdev,
+ void *data, size_t max_len );
+
+#endif /* _GPXE_FAKEDHCP_H */
diff --git a/gpxe/src/include/gpxe/features.h b/gpxe/src/include/gpxe/features.h
new file mode 100644
index 00000000..a520131f
--- /dev/null
+++ b/gpxe/src/include/gpxe/features.h
@@ -0,0 +1,88 @@
+#ifndef _GPXE_FEATURES_H
+#define _GPXE_FEATURES_H
+
+#include <stdint.h>
+#include <gpxe/tables.h>
+#include <gpxe/dhcp.h>
+
+/** @file
+ *
+ * Feature list
+ *
+ */
+
+/**
+ * @defgroup featurecat Feature categories
+ * @{
+ */
+
+#define FEATURE_PROTOCOL 01 /**< Network protocols */
+#define FEATURE_IMAGE 02 /**< Image formats */
+#define FEATURE_MISC 03 /**< Miscellaneous */
+
+/** @} */
+
+/**
+ * @defgroup dhcpfeatures DHCP feature option tags
+ *
+ * DHCP feature option tags are Etherboot encapsulated options in the
+ * range 0x10-0x7f.
+ *
+ * @{
+ */
+
+#define DHCP_EB_FEATURE_PXE_EXT 0x10 /**< PXE API extensions */
+#define DHCP_EB_FEATURE_ISCSI 0x11 /**< iSCSI protocol */
+#define DHCP_EB_FEATURE_AOE 0x12 /**< AoE protocol */
+#define DHCP_EB_FEATURE_HTTP 0x13 /**< HTTP protocol */
+#define DHCP_EB_FEATURE_HTTPS 0x14 /**< HTTPS protocol */
+#define DHCP_EB_FEATURE_TFTP 0x15 /**< TFTP protocol */
+#define DHCP_EB_FEATURE_FTP 0x16 /**< FTP protocol */
+#define DHCP_EB_FEATURE_DNS 0x17 /**< DNS protocol */
+#define DHCP_EB_FEATURE_BZIMAGE 0x18 /**< bzImage format */
+#define DHCP_EB_FEATURE_MULTIBOOT 0x19 /**< Multiboot format */
+#define DHCP_EB_FEATURE_NBI 0x20 /**< NBI format */
+#define DHCP_EB_FEATURE_PXE 0x21 /**< PXE format */
+
+/** @} */
+
+/** Declare a feature code for DHCP */
+#define __dhcp_feature( category ) \
+ __table ( uint8_t, dhcp_features, category )
+
+/** Construct a DHCP feature table entry */
+#define DHCP_FEATURE( category, feature_opt, version ) \
+ _DHCP_FEATURE ( category, OBJECT, feature_opt, version )
+#define _DHCP_FEATURE( category, _name, feature_opt, version ) \
+ __DHCP_FEATURE ( category, _name, feature_opt, version )
+#define __DHCP_FEATURE( category, _name, feature_opt, version ) \
+ uint8_t __dhcp_feature_ ## _name [] __dhcp_feature ( category ) = { \
+ feature_opt, DHCP_BYTE ( version ) \
+ };
+
+/** A named feature */
+struct feature {
+ /** Feature name */
+ char *name;
+};
+
+/** Declare a named feature */
+#define __feature_name( category ) \
+ __table ( struct feature, features, category )
+
+/** Construct a named feature */
+#define FEATURE_NAME( category, text ) \
+ _FEATURE_NAME ( category, OBJECT, text )
+#define _FEATURE_NAME( category, _name, text ) \
+ __FEATURE_NAME ( category, _name, text )
+#define __FEATURE_NAME( category, _name, text ) \
+ struct feature __feature_ ## _name __feature_name ( category ) = { \
+ .name = text, \
+ };
+
+/** Declare a feature */
+#define FEATURE( category, text, feature_opt, version ) \
+ FEATURE_NAME ( category, text ); \
+ DHCP_FEATURE ( category, feature_opt, version );
+
+#endif /* _GPXE_FEATURES_H */
diff --git a/gpxe/src/include/gpxe/filter.h b/gpxe/src/include/gpxe/filter.h
new file mode 100644
index 00000000..126f6347
--- /dev/null
+++ b/gpxe/src/include/gpxe/filter.h
@@ -0,0 +1,73 @@
+#ifndef _GPXE_FILTER_H
+#define _GPXE_FILTER_H
+
+/** @file
+ *
+ * Data transfer filters
+ *
+ */
+
+#include <stddef.h>
+#include <gpxe/xfer.h>
+
+/**
+ * Half of a data transfer filter
+ *
+ * Embed two of these structures within a structure implementing a
+ * data transfer filter, and intialise with filter_init(). You can
+ * then use the filter_xxx() methods as the data transfer interface
+ * methods as required.
+ */
+struct xfer_filter_half {
+ /** Data transfer interface */
+ struct xfer_interface xfer;
+ /** Other half of the data transfer filter */
+ struct xfer_filter_half *other;
+};
+
+/**
+ * Get data transfer interface for the other half of a data transfer filter
+ *
+ * @v xfer Data transfer interface
+ * @ret other Other half's data transfer interface
+ */
+static inline __attribute__ (( always_inline )) struct xfer_interface *
+filter_other_half ( struct xfer_interface *xfer ) {
+ struct xfer_filter_half *half =
+ container_of ( xfer, struct xfer_filter_half, xfer );
+ return &half->other->xfer;
+}
+
+extern void filter_close ( struct xfer_interface *xfer, int rc );
+extern int filter_vredirect ( struct xfer_interface *xfer, int type,
+ va_list args );
+extern size_t filter_window ( struct xfer_interface *xfer );
+extern struct io_buffer * filter_alloc_iob ( struct xfer_interface *xfer,
+ size_t len );
+extern int filter_deliver_iob ( struct xfer_interface *xfer,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta );
+extern int filter_deliver_raw ( struct xfer_interface *xfer, const void *data,
+ size_t len );
+
+/**
+ * Initialise a data transfer filter
+ *
+ * @v left "Left" half of the filter
+ * @v left_op Data transfer interface operations for "left" half
+ * @v right "Right" half of the filter
+ * @v right_op Data transfer interface operations for "right" half
+ * @v refcnt Containing object reference counter, or NULL
+ */
+static inline void filter_init ( struct xfer_filter_half *left,
+ struct xfer_interface_operations *left_op,
+ struct xfer_filter_half *right,
+ struct xfer_interface_operations *right_op,
+ struct refcnt *refcnt ) {
+ xfer_init ( &left->xfer, left_op, refcnt );
+ xfer_init ( &right->xfer, right_op, refcnt );
+ left->other = right;
+ right->other = left;
+}
+
+#endif /* _GPXE_FILTER_H */
diff --git a/gpxe/src/include/gpxe/ftp.h b/gpxe/src/include/gpxe/ftp.h
new file mode 100644
index 00000000..370285c6
--- /dev/null
+++ b/gpxe/src/include/gpxe/ftp.h
@@ -0,0 +1,13 @@
+#ifndef _GPXE_FTP_H
+#define _GPXE_FTP_H
+
+/** @file
+ *
+ * File transfer protocol
+ *
+ */
+
+/** FTP default port */
+#define FTP_PORT 21
+
+#endif /* _GPXE_FTP_H */
diff --git a/gpxe/src/include/gpxe/hidemem.h b/gpxe/src/include/gpxe/hidemem.h
new file mode 100644
index 00000000..547f8881
--- /dev/null
+++ b/gpxe/src/include/gpxe/hidemem.h
@@ -0,0 +1,23 @@
+#ifndef _GPXE_HIDEMEM_H
+#define _GPXE_HIDEMEM_H
+
+/**
+ * @file
+ *
+ * Hidden memory regions
+ *
+ */
+
+/**
+ * Unique IDs for hidden regions
+ */
+enum hidemem_region_id {
+ TEXT = 0,
+ BASEMEM,
+ EXTMEM,
+};
+
+extern void hide_region ( unsigned int region_id, physaddr_t start,
+ physaddr_t end );
+
+#endif /* _GPXE_HIDEMEM_H */
diff --git a/gpxe/src/include/gpxe/hmac.h b/gpxe/src/include/gpxe/hmac.h
new file mode 100644
index 00000000..fd34db04
--- /dev/null
+++ b/gpxe/src/include/gpxe/hmac.h
@@ -0,0 +1,30 @@
+#ifndef _GPXE_HMAC_H
+#define _GPXE_HMAC_H
+
+/** @file
+ *
+ * Keyed-Hashing for Message Authentication
+ */
+
+#include <gpxe/crypto.h>
+
+/**
+ * Update HMAC
+ *
+ * @v digest Digest algorithm to use
+ * @v digest_ctx Digest context
+ * @v data Data
+ * @v len Length of data
+ */
+static inline void hmac_update ( struct crypto_algorithm *digest,
+ void *digest_ctx, const void *data,
+ size_t len ) {
+ digest_update ( digest, digest_ctx, data, len );
+}
+
+extern void hmac_init ( struct crypto_algorithm *digest, void *digest_ctx,
+ void *key, size_t *key_len );
+extern void hmac_final ( struct crypto_algorithm *digest, void *digest_ctx,
+ void *key, size_t *key_len, void *hmac );
+
+#endif /* _GPXE_HMAC_H */
diff --git a/gpxe/src/include/gpxe/http.h b/gpxe/src/include/gpxe/http.h
new file mode 100644
index 00000000..fa92a950
--- /dev/null
+++ b/gpxe/src/include/gpxe/http.h
@@ -0,0 +1,21 @@
+#ifndef _GPXE_HTTP_H
+#define _GPXE_HTTP_H
+
+/** @file
+ *
+ * Hyper Text Transport Protocol
+ *
+ */
+
+/** HTTP default port */
+#define HTTP_PORT 80
+
+/** HTTPS default port */
+#define HTTPS_PORT 443
+
+extern int http_open_filter ( struct xfer_interface *xfer, struct uri *uri,
+ unsigned int default_port,
+ int ( * filter ) ( struct xfer_interface *,
+ struct xfer_interface ** ) );
+
+#endif /* _GPXE_HTTP_H */
diff --git a/gpxe/src/include/gpxe/i2c.h b/gpxe/src/include/gpxe/i2c.h
new file mode 100644
index 00000000..bfaee8fb
--- /dev/null
+++ b/gpxe/src/include/gpxe/i2c.h
@@ -0,0 +1,111 @@
+#ifndef _GPXE_I2C_H
+#define _GPXE_I2C_H
+
+/** @file
+ *
+ * I2C interface
+ *
+ */
+
+#include <stdint.h>
+
+/** An I2C device
+ *
+ * An I2C device represents a specific slave device on an I2C bus. It
+ * is accessed via an I2C interface.
+ */
+struct i2c_device {
+ /** Address of this device */
+ unsigned int address;
+ /** Flag indicating a ten-bit address format */
+ int tenbit;
+};
+
+/** An I2C interface
+ *
+ * An I2C interface provides access to an I2C bus, via which I2C
+ * devices may be reached.
+ */
+struct i2c_interface {
+ /**
+ * Read data from I2C device
+ *
+ * @v i2c I2C interface
+ * @v i2cdev I2C device
+ * @v offset Starting offset within the device
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+ int ( * read ) ( struct i2c_interface *i2c, struct i2c_device *i2cdev,
+ unsigned int offset, uint8_t *data,
+ unsigned int len );
+ /**
+ * Write data to I2C device
+ *
+ * @v i2c I2C interface
+ * @v i2cdev I2C device
+ * @v offset Starting offset within the device
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+ int ( * write ) ( struct i2c_interface *i2c, struct i2c_device *i2cdev,
+ unsigned int offset, const uint8_t *data,
+ unsigned int len );
+};
+
+/** A bit-bashing I2C interface
+ *
+ * This provides a standardised way to construct I2C buses via a
+ * bit-bashing interface.
+ */
+struct i2c_bit_basher {
+ /** I2C interface */
+ struct i2c_interface i2c;
+ /** Bit-bashing interface */
+ struct bit_basher basher;
+};
+
+/** Ten-bit address marker
+ *
+ * This value is ORed with the I2C device address to indicate a
+ * ten-bit address format on the bus.
+ */
+#define I2C_TENBIT_ADDRESS 0x7800
+
+/** An I2C write command */
+#define I2C_WRITE 0
+
+/** An I2C read command */
+#define I2C_READ 1
+
+/** Bit indices used for I2C bit-bashing interface */
+enum {
+ /** Serial clock */
+ I2C_BIT_SCL = 0,
+ /** Serial data */
+ I2C_BIT_SDA,
+};
+
+/** Delay required for bit-bashing operation */
+#define I2C_UDELAY 5
+
+/**
+ * Check presence of I2C device
+ *
+ * @v i2c I2C interface
+ * @v i2cdev I2C device
+ * @ret rc Return status code
+ *
+ * Checks for the presence of the device on the I2C bus by attempting
+ * a zero-length write.
+ */
+static inline int i2c_check_presence ( struct i2c_interface *i2c,
+ struct i2c_device *i2cdev ) {
+ return i2c->write ( i2c, i2cdev, 0, NULL, 0 );
+}
+
+extern void init_i2c_bit_basher ( struct i2c_bit_basher *i2cbit );
+
+#endif /* _GPXE_I2C_H */
diff --git a/gpxe/src/include/gpxe/ibft.h b/gpxe/src/include/gpxe/ibft.h
new file mode 100644
index 00000000..5eef547b
--- /dev/null
+++ b/gpxe/src/include/gpxe/ibft.h
@@ -0,0 +1,300 @@
+#ifndef _GPXE_IBFT_H
+#define _GPXE_IBFT_H
+
+/*
+ * Copyright Fen Systems Ltd. 2007. Portions of this code are derived
+ * from IBM Corporation Sample Programs. Copyright IBM Corporation
+ * 2004, 2007. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/** @file
+ *
+ * iSCSI boot firmware table
+ *
+ * The information in this file is derived from the document "iSCSI
+ * Boot Firmware Table (iBFT)" as published by IBM at
+ *
+ * ftp://ftp.software.ibm.com/systems/support/system_x_pdf/ibm_iscsi_boot_firmware_table_v1.02.pdf
+ *
+ */
+
+#include <stdint.h>
+#include <gpxe/acpi.h>
+#include <gpxe/in.h>
+
+/** iSCSI Boot Firmware Table signature */
+#define IBFT_SIG "iBFT"
+
+/** An offset from the start of the iBFT */
+typedef uint16_t ibft_off_t;
+
+/** Length of a string within the iBFT (excluding terminating NUL) */
+typedef uint16_t ibft_size_t;
+
+/** A string within the iBFT */
+struct ibft_string {
+ /** Length of string */
+ ibft_size_t length;
+ /** Offset to string */
+ ibft_off_t offset;
+} __attribute__ (( packed ));
+
+/** An IP address within the iBFT */
+struct ibft_ipaddr {
+ /** Reserved; must be zero */
+ uint16_t zeroes[5];
+ /** Must be 0xffff if IPv4 address is present, otherwise zero */
+ uint16_t ones;
+ /** The IPv4 address, or zero if not present */
+ struct in_addr in;
+} __attribute__ (( packed ));
+
+/**
+ * iBFT structure header
+ *
+ * This structure is common to several sections within the iBFT.
+ */
+struct ibft_header {
+ /** Structure ID
+ *
+ * This is an IBFT_STRUCTURE_ID_XXX constant
+ */
+ uint8_t structure_id;
+ /** Version (always 1) */
+ uint8_t version;
+ /** Length, including this header */
+ uint16_t length;
+ /** Index
+ *
+ * This is the number of the NIC or Target, when applicable.
+ */
+ uint8_t index;
+ /** Flags */
+ uint8_t flags;
+} __attribute__ (( packed ));
+
+/**
+ * iBFT Control structure
+ *
+ */
+struct ibft_control {
+ /** Common header */
+ struct ibft_header header;
+ /** Extensions */
+ uint16_t extensions;
+ /** Offset to Initiator structure */
+ ibft_off_t initiator;
+ /** Offset to NIC structure for NIC 0 */
+ ibft_off_t nic_0;
+ /** Offset to Target structure for target 0 */
+ ibft_off_t target_0;
+ /** Offset to NIC structure for NIC 1 */
+ ibft_off_t nic_1;
+ /** Offset to Target structure for target 1 */
+ ibft_off_t target_1;
+} __attribute__ (( packed ));
+
+/** Structure ID for Control section */
+#define IBFT_STRUCTURE_ID_CONTROL 0x01
+
+/** Attempt login only to specified target
+ *
+ * If this flag is not set, all targets will be logged in to.
+ */
+#define IBFT_FL_CONTROL_SINGLE_LOGIN_ONLY 0x01
+
+/**
+ * iBFT Initiator structure
+ *
+ */
+struct ibft_initiator {
+ /** Common header */
+ struct ibft_header header;
+ /** iSNS server */
+ struct ibft_ipaddr isns_server;
+ /** SLP server */
+ struct ibft_ipaddr slp_server;
+ /** Primary and secondary Radius servers */
+ struct ibft_ipaddr radius[2];
+ /** Initiator name */
+ struct ibft_string initiator_name;
+} __attribute__ (( packed ));
+
+/** Structure ID for Initiator section */
+#define IBFT_STRUCTURE_ID_INITIATOR 0x02
+
+/** Initiator block valid */
+#define IBFT_FL_INITIATOR_BLOCK_VALID 0x01
+
+/** Initiator firmware boot selected */
+#define IBFT_FL_INITIATOR_FIRMWARE_BOOT_SELECTED 0x02
+
+/**
+ * iBFT NIC structure
+ *
+ */
+struct ibft_nic {
+ /** Common header */
+ struct ibft_header header;
+ /** IP address */
+ struct ibft_ipaddr ip_address;
+ /** Subnet mask
+ *
+ * This is the length of the subnet mask in bits (e.g. /24).
+ */
+ uint8_t subnet_mask_prefix;
+ /** Origin */
+ uint8_t origin;
+ /** Default gateway */
+ struct ibft_ipaddr gateway;
+ /** Primary and secondary DNS servers */
+ struct ibft_ipaddr dns[2];
+ /** DHCP server */
+ struct ibft_ipaddr dhcp;
+ /** VLAN tag */
+ uint16_t vlan;
+ /** MAC address */
+ uint8_t mac_address[6];
+ /** PCI bus:dev:fn */
+ uint16_t pci_bus_dev_func;
+ /** Hostname */
+ struct ibft_string hostname;
+} __attribute__ (( packed ));
+
+/** Structure ID for NIC section */
+#define IBFT_STRUCTURE_ID_NIC 0x03
+
+/** NIC block valid */
+#define IBFT_FL_NIC_BLOCK_VALID 0x01
+
+/** NIC firmware boot selected */
+#define IBFT_FL_NIC_FIRMWARE_BOOT_SELECTED 0x02
+
+/** NIC global / link local */
+#define IBFT_FL_NIC_GLOBAL 0x04
+
+/**
+ * iBFT Target structure
+ *
+ */
+struct ibft_target {
+ /** Common header */
+ struct ibft_header header;
+ /** IP address */
+ struct ibft_ipaddr ip_address;
+ /** TCP port */
+ uint16_t socket;
+ /** Boot LUN */
+ uint64_t boot_lun;
+ /** CHAP type
+ *
+ * This is an IBFT_CHAP_XXX constant.
+ */
+ uint8_t chap_type;
+ /** NIC association */
+ uint8_t nic_association;
+ /** Target name */
+ struct ibft_string target_name;
+ /** CHAP name */
+ struct ibft_string chap_name;
+ /** CHAP secret */
+ struct ibft_string chap_secret;
+ /** Reverse CHAP name */
+ struct ibft_string reverse_chap_name;
+ /** Reverse CHAP secret */
+ struct ibft_string reverse_chap_secret;
+} __attribute__ (( packed ));
+
+/** Structure ID for Target section */
+#define IBFT_STRUCTURE_ID_TARGET 0x04
+
+/** Target block valid */
+#define IBFT_FL_TARGET_BLOCK_VALID 0x01
+
+/** Target firmware boot selected */
+#define IBFT_FL_TARGET_FIRMWARE_BOOT_SELECTED 0x02
+
+/** Target use Radius CHAP */
+#define IBFT_FL_TARGET_USE_CHAP 0x04
+
+/** Target use Radius rCHAP */
+#define IBFT_FL_TARGET_USE_RCHAP 0x08
+
+/* Values for chap_type */
+#define IBFT_CHAP_NONE 0 /**< No CHAP authentication */
+#define IBFT_CHAP_ONE_WAY 1 /**< One-way CHAP */
+#define IBFT_CHAP_MUTUAL 2 /**< Mutual CHAP */
+
+/**
+ * iSCSI Boot Firmware Table (iBFT)
+ */
+struct ibft_table {
+ /** ACPI header */
+ struct acpi_description_header acpi;
+ /** Reserved */
+ uint8_t reserved[12];
+ /** Control structure */
+ struct ibft_control control;
+} __attribute__ (( packed ));
+
+/**
+ * iSCSI string block descriptor
+ *
+ * This is an internal structure that we use to keep track of the
+ * allocation of string data.
+ */
+struct ibft_string_block {
+ /** The iBFT containing these strings */
+ struct ibft_table *table;
+ /** Offset of first free byte within iBFT */
+ unsigned int offset;
+};
+
+/** Amount of space reserved for strings in a gPXE iBFT */
+#define IBFT_STRINGS_SIZE 384
+
+/**
+ * An iBFT created by gPXE
+ *
+ */
+struct gpxe_ibft {
+ /** The fixed section */
+ struct ibft_table table;
+ /** The Initiator section */
+ struct ibft_initiator initiator __attribute__ (( aligned ( 16 ) ));
+ /** The NIC section */
+ struct ibft_nic nic __attribute__ (( aligned ( 16 ) ));
+ /** The Target section */
+ struct ibft_target target __attribute__ (( aligned ( 16 ) ));
+ /** Strings block */
+ char strings[IBFT_STRINGS_SIZE];
+} __attribute__ (( packed, aligned ( 16 ) ));
+
+struct net_device;
+struct iscsi_session;
+
+extern int ibft_fill_data ( struct net_device *netdev,
+ struct iscsi_session *iscsi );
+
+#endif /* _GPXE_IBFT_H */
diff --git a/gpxe/src/include/gpxe/icmp6.h b/gpxe/src/include/gpxe/icmp6.h
new file mode 100644
index 00000000..34093616
--- /dev/null
+++ b/gpxe/src/include/gpxe/icmp6.h
@@ -0,0 +1,57 @@
+#ifndef _GPXE_ICMP6_H
+#define _GPXE_ICMP6_H
+
+/** @file
+ *
+ * ICMP6 protocol
+ *
+ */
+
+#include <gpxe/ip6.h>
+#include <gpxe/ndp.h>
+
+#define ICMP6_NSOLICIT 135
+#define ICMP6_NADVERT 136
+
+extern struct tcpip_protocol icmp6_protocol;
+
+struct icmp6_header {
+ uint8_t type;
+ uint8_t code;
+ uint16_t csum;
+ /* Message body */
+};
+
+struct neighbour_solicit {
+ uint8_t type;
+ uint8_t code;
+ uint16_t csum;
+ uint32_t reserved;
+ struct in6_addr target;
+ /* "Compulsory" options */
+ uint8_t opt_type;
+ uint8_t opt_len;
+ /* FIXME: hack alert */
+ uint8_t opt_ll_addr[6];
+};
+
+struct neighbour_advert {
+ uint8_t type;
+ uint8_t code;
+ uint16_t csum;
+ uint8_t flags;
+ uint8_t reserved;
+ struct in6_addr target;
+ uint8_t opt_type;
+ uint8_t opt_len;
+ /* FIXME: hack alert */
+ uint8_t opt_ll_addr[6];
+};
+
+#define ICMP6_FLAGS_ROUTER 0x80
+#define ICMP6_FLAGS_SOLICITED 0x40
+#define ICMP6_FLAGS_OVERRIDE 0x20
+
+int icmp6_send_solicit ( struct net_device *netdev, struct in6_addr *src, struct in6_addr *dest );
+
+#endif /* _GPXE_ICMP6_H */
diff --git a/gpxe/src/include/gpxe/if_arp.h b/gpxe/src/include/gpxe/if_arp.h
new file mode 100644
index 00000000..5b250337
--- /dev/null
+++ b/gpxe/src/include/gpxe/if_arp.h
@@ -0,0 +1,100 @@
+#ifndef _GPXE_IF_ARP_H
+#define _GPXE_IF_ARP_H
+
+/** @file
+ *
+ * Address Resolution Protocol constants and types
+ *
+ */
+
+#include <stdint.h>
+
+/* ARP protocol HARDWARE identifiers. */
+#define ARPHRD_NETROM 0 /**< from KA9Q: NET/ROM pseudo */
+#define ARPHRD_ETHER 1 /**< Ethernet 10Mbps */
+#define ARPHRD_EETHER 2 /**< Experimental Ethernet */
+#define ARPHRD_AX25 3 /**< AX.25 Level 2 */
+#define ARPHRD_PRONET 4 /**< PROnet token ring */
+#define ARPHRD_CHAOS 5 /**< Chaosnet */
+#define ARPHRD_IEEE802 6 /**< IEEE 802.2 Ethernet/TR/TB */
+#define ARPHRD_ARCNET 7 /**< ARCnet */
+#define ARPHRD_APPLETLK 8 /**< APPLEtalk */
+#define ARPHRD_DLCI 15 /**< Frame Relay DLCI */
+#define ARPHRD_ATM 19 /**< ATM */
+#define ARPHRD_METRICOM 23 /**< Metricom STRIP (new IANA id) */
+#define ARPHRD_IEEE1394 24 /**< IEEE 1394 IPv4 - RFC 2734 */
+#define ARPHRD_EUI64 27 /**< EUI-64 */
+#define ARPHRD_INFINIBAND 32 /**< InfiniBand */
+
+/* ARP protocol opcodes. */
+#define ARPOP_REQUEST 1 /**< ARP request */
+#define ARPOP_REPLY 2 /**< ARP reply */
+#define ARPOP_RREQUEST 3 /**< RARP request */
+#define ARPOP_RREPLY 4 /**< RARP reply */
+#define ARPOP_InREQUEST 8 /**< InARP request */
+#define ARPOP_InREPLY 9 /**< InARP reply */
+#define ARPOP_NAK 10 /**< (ATM)ARP NAK */
+
+/**
+ * An ARP header
+ *
+ * This contains only the fixed-size portions of an ARP header; for
+ * other fields use the arp_{sender,target}_{ha,pa} family of
+ * functions.
+ */
+struct arphdr {
+ /** Link-layer protocol
+ *
+ * This is an ARPHRD_XXX constant
+ */
+ uint16_t ar_hrd;
+ /** Network-layer protocol
+ *
+ * This is, for Ethernet, an ETH_P_XXX constant.
+ */
+ uint16_t ar_pro;
+ /** Link-layer address length */
+ uint8_t ar_hln;
+ /** Network-layer address length */
+ uint8_t ar_pln;
+ /** ARP opcode */
+ uint16_t ar_op;
+} __attribute__ (( packed ));
+
+/** ARP packet sender hardware address
+ *
+ * @v arphdr ARP header
+ * @ret ar_sha Sender hardware address
+ */
+static inline void * arp_sender_ha ( struct arphdr *arphdr ) {
+ return ( ( ( void * ) arphdr ) + sizeof ( *arphdr ) );
+}
+
+/** ARP packet sender protocol address
+ *
+ * @v arphdr ARP header
+ * @ret ar_spa Sender protocol address
+ */
+static inline void * arp_sender_pa ( struct arphdr *arphdr ) {
+ return ( arp_sender_ha ( arphdr ) + arphdr->ar_hln );
+}
+
+/** ARP packet target hardware address
+ *
+ * @v arphdr ARP header
+ * @ret ar_tha Target hardware address
+ */
+static inline void * arp_target_ha ( struct arphdr *arphdr ) {
+ return ( arp_sender_pa ( arphdr ) + arphdr->ar_pln );
+}
+
+/** ARP packet target protocol address
+ *
+ * @v arphdr ARP header
+ * @ret ar_tpa Target protocol address
+ */
+static inline void * arp_target_pa ( struct arphdr *arphdr ) {
+ return ( arp_target_ha ( arphdr ) + arphdr->ar_hln );
+}
+
+#endif /* _GPXE_IF_ARP_H */
diff --git a/gpxe/src/include/gpxe/if_ether.h b/gpxe/src/include/gpxe/if_ether.h
new file mode 100644
index 00000000..2f3f33d4
--- /dev/null
+++ b/gpxe/src/include/gpxe/if_ether.h
@@ -0,0 +1,33 @@
+#ifndef _GPXE_IF_ETHER_H
+#define _GPXE_IF_ETHER_H
+
+#include <stdint.h>
+
+#define ETH_ALEN 6 /* Size of Ethernet address */
+#define ETH_HLEN 14 /* Size of ethernet header */
+#define ETH_ZLEN 60 /* Minimum packet */
+#define ETH_FRAME_LEN 1514 /* Maximum packet */
+#define ETH_DATA_ALIGN 2 /* Amount needed to align the data after an ethernet header */
+#ifndef ETH_MAX_MTU
+#define ETH_MAX_MTU (ETH_FRAME_LEN-ETH_HLEN)
+#endif
+
+#define ETH_P_RAW 0x0000 /* Raw packet */
+#define ETH_P_IP 0x0800 /* Internet Protocl Packet */
+#define ETH_P_ARP 0x0806 /* Address Resolution Protocol */
+#define ETH_P_RARP 0x8035 /* Reverse Address resolution Protocol */
+#define ETH_P_IPV6 0x86DD /* IPv6 over blueblook */
+#define ETH_P_SLOW 0x8809 /* Ethernet slow protocols */
+#define ETH_P_AOE 0x88A2 /* ATA over Ethernet */
+
+/** An Ethernet link-layer header */
+struct ethhdr {
+ /** Destination MAC address */
+ uint8_t h_dest[ETH_ALEN];
+ /** Source MAC address */
+ uint8_t h_source[ETH_ALEN];
+ /** Protocol ID */
+ uint16_t h_protocol;
+} __attribute__ ((packed));
+
+#endif /* _GPXE_IF_ETHER_H */
diff --git a/gpxe/src/include/gpxe/image.h b/gpxe/src/include/gpxe/image.h
new file mode 100644
index 00000000..76dc3b8f
--- /dev/null
+++ b/gpxe/src/include/gpxe/image.h
@@ -0,0 +1,162 @@
+#ifndef _GPXE_IMAGE_H
+#define _GPXE_IMAGE_H
+
+/**
+ * @file
+ *
+ * Executable/loadable images
+ *
+ */
+
+#include <gpxe/tables.h>
+#include <gpxe/list.h>
+#include <gpxe/uaccess.h>
+#include <gpxe/refcnt.h>
+
+struct uri;
+struct image_type;
+
+/** An executable or loadable image */
+struct image {
+ /** Reference count */
+ struct refcnt refcnt;
+
+ /** List of registered images */
+ struct list_head list;
+
+ /** URI of image */
+ struct uri *uri;
+ /** Name */
+ char name[16];
+ /** Flags */
+ unsigned int flags;
+
+ /** Command line to pass to image */
+ char *cmdline;
+ /** Raw file image */
+ userptr_t data;
+ /** Length of raw file image */
+ size_t len;
+
+ /** Image type, if known */
+ struct image_type *type;
+ /** Image type private data */
+ union {
+ physaddr_t phys;
+ userptr_t user;
+ unsigned long ul;
+ } priv;
+};
+
+/** Image is loaded */
+#define IMAGE_LOADED 0x0001
+
+/** An executable or loadable image type */
+struct image_type {
+ /** Name of this image type */
+ char *name;
+ /**
+ * Load image into memory
+ *
+ * @v image Executable/loadable image
+ * @ret rc Return status code
+ *
+ * Load the image into memory at the correct location as
+ * determined by the file format.
+ *
+ * If the file image is in the correct format, the method must
+ * update @c image->type to point to its own type (unless @c
+ * image->type is already set). This allows the autoloading
+ * code to disambiguate between "this is not my image format"
+ * and "there is something wrong with this image". In
+ * particular, setting @c image->type and then returning an
+ * error will cause image_autoload() to abort and return an
+ * error, rather than continuing to the next image type.
+ */
+ int ( * load ) ( struct image *image );
+ /**
+ * Execute loaded image
+ *
+ * @v image Loaded image
+ * @ret rc Return status code
+ */
+ int ( * exec ) ( struct image *image );
+};
+
+/**
+ * Multiboot image probe priority
+ *
+ * Multiboot images are also valid executables in another format
+ * (e.g. ELF), so we must perform the multiboot probe first.
+ */
+#define PROBE_MULTIBOOT 01
+
+/**
+ * Normal image probe priority
+ */
+#define PROBE_NORMAL 02
+
+/**
+ * PXE image probe priority
+ *
+ * PXE images have no signature checks, so will claim all image files.
+ * They must therefore be tried last in the probe order list.
+ */
+#define PROBE_PXE 03
+
+/** An executable or loadable image type */
+#define __image_type( probe_order ) \
+ __table ( struct image_type, image_types, probe_order )
+
+extern struct list_head images;
+
+/** Iterate over all registered images */
+#define for_each_image( image ) \
+ list_for_each_entry ( (image), &images, list )
+
+extern struct image * alloc_image ( void );
+extern int image_set_uri ( struct image *image, struct uri *uri );
+extern int image_set_cmdline ( struct image *image, const char *cmdline );
+extern int register_image ( struct image *image );
+extern void unregister_image ( struct image *image );
+extern void promote_image ( struct image *image );
+struct image * find_image ( const char *name );
+extern int image_load ( struct image *image );
+extern int image_autoload ( struct image *image );
+extern int image_exec ( struct image *image );
+extern int register_and_autoload_image ( struct image *image );
+extern int register_and_autoexec_image ( struct image *image );
+
+/**
+ * Increment reference count on an image
+ *
+ * @v image Image
+ * @ret image Image
+ */
+static inline struct image * image_get ( struct image *image ) {
+ ref_get ( &image->refcnt );
+ return image;
+}
+
+/**
+ * Decrement reference count on an image
+ *
+ * @v image Image
+ */
+static inline void image_put ( struct image *image ) {
+ ref_put ( &image->refcnt );
+}
+
+/**
+ * Set image name
+ *
+ * @v image Image
+ * @v name New image name
+ * @ret rc Return status code
+ */
+static inline int image_set_name ( struct image *image, const char *name ) {
+ strncpy ( image->name, name, ( sizeof ( image->name ) - 1 ) );
+ return 0;
+}
+
+#endif /* _GPXE_IMAGE_H */
diff --git a/gpxe/src/include/gpxe/in.h b/gpxe/src/include/gpxe/in.h
new file mode 100644
index 00000000..89530a55
--- /dev/null
+++ b/gpxe/src/include/gpxe/in.h
@@ -0,0 +1,94 @@
+#ifndef _GPXE_IN_H
+#define _GPXE_IN_H
+
+#include <stdint.h>
+#include <gpxe/socket.h>
+
+/* Protocol numbers */
+
+#define IP_ICMP 1
+#define IP_IGMP 2
+#define IP_TCP 6
+#define IP_UDP 17
+#define IP_ICMP6 58
+
+/* IP address constants */
+
+#define INADDR_NONE 0xffffffff
+
+#define INADDR_BROADCAST 0xffffffff
+
+#define IN_CLASSA(addr) ( ( (addr) & 0x80000000 ) == 0x00000000 )
+#define IN_CLASSA_NET 0xff000000
+#define IN_CLASSB(addr) ( ( (addr) & 0xc0000000 ) == 0x80000000 )
+#define IN_CLASSB_NET 0xffff0000
+#define IN_CLASSC(addr) ( ( (addr) & 0xe0000000 ) == 0xc0000000 )
+#define IN_CLASSC_NET 0xffffff00
+#define IN_MULTICAST(addr) ( ( (addr) & 0xf0000000 ) == 0xe0000000 )
+
+/**
+ * IP address structure
+ */
+struct in_addr {
+ uint32_t s_addr;
+};
+
+typedef struct in_addr in_addr;
+
+/**
+ * IP6 address structure
+ */
+struct in6_addr {
+ union {
+ uint8_t u6_addr8[16];
+ uint16_t u6_addr16[8];
+ uint32_t u6_addr32[4];
+ } in6_u;
+#define s6_addr in6_u.u6_addr8
+#define s6_addr16 in6_u.u6_addr16
+#define s6_addr32 in6_u.u6_addr32
+};
+
+/**
+ * IPv4 socket address
+ */
+struct sockaddr_in {
+ /** Socket address family (part of struct @c sockaddr)
+ *
+ * Always set to @c AF_INET for IPv4 addresses
+ */
+ sa_family_t sin_family;
+ /** TCP/IP port (part of struct @c sockaddr_tcpip) */
+ uint16_t sin_port;
+ /** IPv4 address */
+ struct in_addr sin_addr;
+};
+
+/**
+ * IPv6 socket address
+ */
+struct sockaddr_in6 {
+ /** Socket address family (part of struct @c sockaddr)
+ *
+ * Always set to @c AF_INET6 for IPv6 addresses
+ */
+ sa_family_t sin_family;
+ /** TCP/IP port (part of struct @c sockaddr_tcpip) */
+ uint16_t sin_port;
+ uint32_t sin6_flowinfo; /* Flow number */
+ struct in6_addr sin6_addr; /* 128-bit destination address */
+ uint32_t sin6_scope_id; /* Scope ID */
+};
+
+extern int inet_aton ( const char *cp, struct in_addr *inp );
+extern char * inet_ntoa ( struct in_addr in );
+
+/* Adding the following for IP6 support
+ *
+
+extern int inet6_aton ( const char *cp, struct in6_addr *inp );
+extern char * inet6_ntoa ( struct in_addr in );
+
+ */
+
+#endif /* _GPXE_IN_H */
diff --git a/gpxe/src/include/gpxe/infiniband.h b/gpxe/src/include/gpxe/infiniband.h
new file mode 100644
index 00000000..354dc579
--- /dev/null
+++ b/gpxe/src/include/gpxe/infiniband.h
@@ -0,0 +1,751 @@
+#ifndef _GPXE_INFINIBAND_H
+#define _GPXE_INFINIBAND_H
+
+/** @file
+ *
+ * Infiniband protocol
+ *
+ */
+
+#include <stdint.h>
+#include <gpxe/device.h>
+
+/** Subnet administrator QPN */
+#define IB_SA_QPN 1
+
+/** Broadcast QPN */
+#define IB_BROADCAST_QPN 0xffffffUL
+
+/** Subnet administrator queue key */
+#define IB_GLOBAL_QKEY 0x80010000UL
+
+/** An Infiniband Global Identifier */
+struct ib_gid {
+ union {
+ uint8_t bytes[16];
+ uint16_t words[8];
+ uint32_t dwords[4];
+ } u;
+};
+
+/** An Infiniband Global Route Header */
+struct ib_global_route_header {
+ /** IP version, traffic class, and flow label
+ *
+ * 4 bits : Version of the GRH
+ * 8 bits : Traffic class
+ * 20 bits : Flow label
+ */
+ uint32_t ipver_tclass_flowlabel;
+ /** Payload length */
+ uint16_t paylen;
+ /** Next header */
+ uint8_t nxthdr;
+ /** Hop limit */
+ uint8_t hoplmt;
+ /** Source GID */
+ struct ib_gid sgid;
+ /** Destiniation GID */
+ struct ib_gid dgid;
+} __attribute__ (( packed ));
+
+struct ib_device;
+struct ib_queue_pair;
+struct ib_completion_queue;
+
+/** An Infiniband Work Queue */
+struct ib_work_queue {
+ /** Containing queue pair */
+ struct ib_queue_pair *qp;
+ /** "Is a send queue" flag */
+ int is_send;
+ /** Associated completion queue */
+ struct ib_completion_queue *cq;
+ /** List of work queues on this completion queue */
+ struct list_head list;
+ /** Number of work queue entries */
+ unsigned int num_wqes;
+ /** Next work queue entry index
+ *
+ * This is the index of the next entry to be filled (i.e. the
+ * first empty entry). This value is not bounded by num_wqes;
+ * users must logical-AND with (num_wqes-1) to generate an
+ * array index.
+ */
+ unsigned long next_idx;
+ /** I/O buffers assigned to work queue */
+ struct io_buffer **iobufs;
+ /** Driver private data */
+ void *drv_priv;
+};
+
+/** An Infiniband Queue Pair */
+struct ib_queue_pair {
+ /** Queue Pair Number */
+ unsigned long qpn;
+ /** Queue key */
+ unsigned long qkey;
+ /** Send queue */
+ struct ib_work_queue send;
+ /** Receive queue */
+ struct ib_work_queue recv;
+ /** Driver private data */
+ void *drv_priv;
+ /** Queue owner private data */
+ void *owner_priv;
+};
+
+/** An Infiniband Completion Queue */
+struct ib_completion_queue {
+ /** Completion queue number */
+ unsigned long cqn;
+ /** Number of completion queue entries */
+ unsigned int num_cqes;
+ /** Next completion queue entry index
+ *
+ * This is the index of the next entry to be filled (i.e. the
+ * first empty entry). This value is not bounded by num_wqes;
+ * users must logical-AND with (num_wqes-1) to generate an
+ * array index.
+ */
+ unsigned long next_idx;
+ /** List of work queues completing to this queue */
+ struct list_head work_queues;
+ /** Driver private data */
+ void *drv_priv;
+};
+
+/** An Infiniband completion */
+struct ib_completion {
+ /** Syndrome
+ *
+ * If non-zero, then the completion is in error.
+ */
+ unsigned int syndrome;
+ /** Length */
+ size_t len;
+};
+
+/** An Infiniband completion handler
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v completion Completion
+ * @v iobuf I/O buffer
+ */
+typedef void ( * ib_completer_t ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_completion *completion,
+ struct io_buffer *iobuf );
+
+/** An Infiniband Address Vector */
+struct ib_address_vector {
+ /** Destination Queue Pair */
+ unsigned int dest_qp;
+ /** Queue key */
+ unsigned long qkey;
+ /** Destination Local ID */
+ unsigned int dlid;
+ /** Rate */
+ unsigned int rate;
+ /** Service level */
+ unsigned int sl;
+ /** GID is present */
+ unsigned int gid_present;
+ /** GID */
+ struct ib_gid gid;
+};
+
+struct ib_mad_hdr;
+
+/**
+ * Infiniband device operations
+ *
+ * These represent a subset of the Infiniband Verbs.
+ */
+struct ib_device_operations {
+ /** Create completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ * @ret rc Return status code
+ */
+ int ( * create_cq ) ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq );
+ /** Destroy completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ */
+ void ( * destroy_cq ) ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq );
+ /** Create queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @ret rc Return status code
+ */
+ int ( * create_qp ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp );
+ /** Destroy queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ */
+ void ( * destroy_qp ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp );
+ /** Post send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ *
+ * If this method returns success, the I/O buffer remains
+ * owned by the queue pair. If this method returns failure,
+ * the I/O buffer is immediately released; the failure is
+ * interpreted as "failure to enqueue buffer".
+ */
+ int ( * post_send ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf );
+ /** Post receive work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ *
+ * If this method returns success, the I/O buffer remains
+ * owned by the queue pair. If this method returns failure,
+ * the I/O buffer is immediately released; the failure is
+ * interpreted as "failure to enqueue buffer".
+ */
+ int ( * post_recv ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct io_buffer *iobuf );
+ /** Poll completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ * @v complete_send Send completion handler
+ * @v complete_recv Receive completion handler
+ *
+ * The completion handler takes ownership of the I/O buffer.
+ */
+ void ( * poll_cq ) ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq,
+ ib_completer_t complete_send,
+ ib_completer_t complete_recv );
+ /**
+ * Open port
+ *
+ * @v ibdev Infiniband device
+ * @ret rc Return status code
+ */
+ int ( * open ) ( struct ib_device *ibdev );
+ /**
+ * Close port
+ *
+ * @v ibdev Infiniband device
+ */
+ void ( * close ) ( struct ib_device *ibdev );
+ /** Attach to multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ * @ret rc Return status code
+ */
+ int ( * mcast_attach ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_gid *gid );
+ /** Detach from multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ */
+ void ( * mcast_detach ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_gid *gid );
+ /**
+ * Issue management datagram
+ *
+ * @v ibdev Infiniband device
+ * @v mad Management datagram
+ * @v len Length of management datagram
+ * @ret rc Return status code
+ */
+ int ( * mad ) ( struct ib_device *ibdev, struct ib_mad_hdr *mad,
+ size_t len );
+};
+
+/** An Infiniband device */
+struct ib_device {
+ /** Underlying device */
+ struct device *dev;
+ /** Infiniband operations */
+ struct ib_device_operations *op;
+ /** Port number */
+ unsigned int port;
+ /** Port GID */
+ struct ib_gid port_gid;
+ /** Subnet manager LID */
+ unsigned long sm_lid;
+ /** Partition key */
+ unsigned int pkey;
+ /** Driver private data */
+ void *drv_priv;
+ /** Owner private data */
+ void *owner_priv;
+};
+
+extern struct ib_completion_queue * ib_create_cq ( struct ib_device *ibdev,
+ unsigned int num_cqes );
+extern void ib_destroy_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq );
+extern struct ib_queue_pair *
+ib_create_qp ( struct ib_device *ibdev, unsigned int num_send_wqes,
+ struct ib_completion_queue *send_cq, unsigned int num_recv_wqes,
+ struct ib_completion_queue *recv_cq, unsigned long qkey );
+extern void ib_destroy_qp ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp );
+extern struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq,
+ unsigned long qpn, int is_send );
+extern struct ib_device * alloc_ibdev ( size_t priv_size );
+extern int register_ibdev ( struct ib_device *ibdev );
+extern void unregister_ibdev ( struct ib_device *ibdev );
+extern void free_ibdev ( struct ib_device *ibdev );
+
+/**
+ * Post send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static inline __attribute__ (( always_inline )) int
+ib_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_address_vector *av, struct io_buffer *iobuf ) {
+ return ibdev->op->post_send ( ibdev, qp, av, iobuf );
+}
+
+/**
+ * Post receive work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static inline __attribute__ (( always_inline )) int
+ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct io_buffer *iobuf ) {
+ return ibdev->op->post_recv ( ibdev, qp, iobuf );
+}
+
+/**
+ * Poll completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ * @v complete_send Send completion handler
+ * @v complete_recv Receive completion handler
+ */
+static inline __attribute__ (( always_inline )) void
+ib_poll_cq ( struct ib_device *ibdev, struct ib_completion_queue *cq,
+ ib_completer_t complete_send, ib_completer_t complete_recv ) {
+ ibdev->op->poll_cq ( ibdev, cq, complete_send, complete_recv );
+}
+
+/**
+ * Open port
+ *
+ * @v ibdev Infiniband device
+ * @ret rc Return status code
+ */
+static inline __attribute__ (( always_inline )) int
+ib_open ( struct ib_device *ibdev ) {
+ return ibdev->op->open ( ibdev );
+}
+
+/**
+ * Close port
+ *
+ * @v ibdev Infiniband device
+ */
+static inline __attribute__ (( always_inline )) void
+ib_close ( struct ib_device *ibdev ) {
+ ibdev->op->close ( ibdev );
+}
+
+/**
+ * Attach to multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ * @ret rc Return status code
+ */
+static inline __attribute__ (( always_inline )) int
+ib_mcast_attach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_gid *gid ) {
+ return ibdev->op->mcast_attach ( ibdev, qp, gid );
+}
+
+/**
+ * Detach from multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ */
+static inline __attribute__ (( always_inline )) void
+ib_mcast_detach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_gid *gid ) {
+ ibdev->op->mcast_detach ( ibdev, qp, gid );
+}
+
+/**
+ * Issue management datagram
+ *
+ * @v ibdev Infiniband device
+ * @v mad Management datagram
+ * @v len Length of management datagram
+ * @ret rc Return status code
+ */
+static inline __attribute__ (( always_inline )) int
+ib_mad ( struct ib_device *ibdev, struct ib_mad_hdr *mad, size_t len ) {
+ return ibdev->op->mad ( ibdev, mad, len );
+}
+
+/**
+ * Set Infiniband work queue driver-private data
+ *
+ * @v wq Work queue
+ * @v priv Private data
+ */
+static inline __attribute__ (( always_inline )) void
+ib_wq_set_drvdata ( struct ib_work_queue *wq, void *priv ) {
+ wq->drv_priv = priv;
+}
+
+/**
+ * Get Infiniband work queue driver-private data
+ *
+ * @v wq Work queue
+ * @ret priv Private data
+ */
+static inline __attribute__ (( always_inline )) void *
+ib_wq_get_drvdata ( struct ib_work_queue *wq ) {
+ return wq->drv_priv;
+}
+
+/**
+ * Set Infiniband queue pair driver-private data
+ *
+ * @v qp Queue pair
+ * @v priv Private data
+ */
+static inline __attribute__ (( always_inline )) void
+ib_qp_set_drvdata ( struct ib_queue_pair *qp, void *priv ) {
+ qp->drv_priv = priv;
+}
+
+/**
+ * Get Infiniband queue pair driver-private data
+ *
+ * @v qp Queue pair
+ * @ret priv Private data
+ */
+static inline __attribute__ (( always_inline )) void *
+ib_qp_get_drvdata ( struct ib_queue_pair *qp ) {
+ return qp->drv_priv;
+}
+
+/**
+ * Set Infiniband queue pair owner-private data
+ *
+ * @v qp Queue pair
+ * @v priv Private data
+ */
+static inline __attribute__ (( always_inline )) void
+ib_qp_set_ownerdata ( struct ib_queue_pair *qp, void *priv ) {
+ qp->owner_priv = priv;
+}
+
+/**
+ * Get Infiniband queue pair owner-private data
+ *
+ * @v qp Queue pair
+ * @ret priv Private data
+ */
+static inline __attribute__ (( always_inline )) void *
+ib_qp_get_ownerdata ( struct ib_queue_pair *qp ) {
+ return qp->owner_priv;
+}
+
+/**
+ * Set Infiniband completion queue driver-private data
+ *
+ * @v cq Completion queue
+ * @v priv Private data
+ */
+static inline __attribute__ (( always_inline )) void
+ib_cq_set_drvdata ( struct ib_completion_queue *cq, void *priv ) {
+ cq->drv_priv = priv;
+}
+
+/**
+ * Get Infiniband completion queue driver-private data
+ *
+ * @v cq Completion queue
+ * @ret priv Private data
+ */
+static inline __attribute__ (( always_inline )) void *
+ib_cq_get_drvdata ( struct ib_completion_queue *cq ) {
+ return cq->drv_priv;
+}
+
+/**
+ * Set Infiniband device driver-private data
+ *
+ * @v ibdev Infiniband device
+ * @v priv Private data
+ */
+static inline __attribute__ (( always_inline )) void
+ib_set_drvdata ( struct ib_device *ibdev, void *priv ) {
+ ibdev->drv_priv = priv;
+}
+
+/**
+ * Get Infiniband device driver-private data
+ *
+ * @v ibdev Infiniband device
+ * @ret priv Private data
+ */
+static inline __attribute__ (( always_inline )) void *
+ib_get_drvdata ( struct ib_device *ibdev ) {
+ return ibdev->drv_priv;
+}
+
+/**
+ * Set Infiniband device owner-private data
+ *
+ * @v ibdev Infiniband device
+ * @v priv Private data
+ */
+static inline __attribute__ (( always_inline )) void
+ib_set_ownerdata ( struct ib_device *ibdev, void *priv ) {
+ ibdev->owner_priv = priv;
+}
+
+/**
+ * Get Infiniband device owner-private data
+ *
+ * @v ibdev Infiniband device
+ * @ret priv Private data
+ */
+static inline __attribute__ (( always_inline )) void *
+ib_get_ownerdata ( struct ib_device *ibdev ) {
+ return ibdev->owner_priv;
+}
+
+/*****************************************************************************
+ *
+ * Management datagrams
+ *
+ * Portions Copyright (c) 2004 Mellanox Technologies Ltd. All rights
+ * reserved.
+ *
+ */
+
+/* Management base version */
+#define IB_MGMT_BASE_VERSION 1
+
+/* Management classes */
+#define IB_MGMT_CLASS_SUBN_LID_ROUTED 0x01
+#define IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE 0x81
+#define IB_MGMT_CLASS_SUBN_ADM 0x03
+#define IB_MGMT_CLASS_PERF_MGMT 0x04
+#define IB_MGMT_CLASS_BM 0x05
+#define IB_MGMT_CLASS_DEVICE_MGMT 0x06
+#define IB_MGMT_CLASS_CM 0x07
+#define IB_MGMT_CLASS_SNMP 0x08
+#define IB_MGMT_CLASS_VENDOR_RANGE2_START 0x30
+#define IB_MGMT_CLASS_VENDOR_RANGE2_END 0x4F
+
+/* Management methods */
+#define IB_MGMT_METHOD_GET 0x01
+#define IB_MGMT_METHOD_SET 0x02
+#define IB_MGMT_METHOD_GET_RESP 0x81
+#define IB_MGMT_METHOD_SEND 0x03
+#define IB_MGMT_METHOD_TRAP 0x05
+#define IB_MGMT_METHOD_REPORT 0x06
+#define IB_MGMT_METHOD_REPORT_RESP 0x86
+#define IB_MGMT_METHOD_TRAP_REPRESS 0x07
+#define IB_MGMT_METHOD_DELETE 0x15
+#define IB_MGMT_METHOD_RESP 0x80
+
+/* Subnet management attributes */
+#define IB_SMP_ATTR_NOTICE 0x0002
+#define IB_SMP_ATTR_NODE_DESC 0x0010
+#define IB_SMP_ATTR_NODE_INFO 0x0011
+#define IB_SMP_ATTR_SWITCH_INFO 0x0012
+#define IB_SMP_ATTR_GUID_INFO 0x0014
+#define IB_SMP_ATTR_PORT_INFO 0x0015
+#define IB_SMP_ATTR_PKEY_TABLE 0x0016
+#define IB_SMP_ATTR_SL_TO_VL_TABLE 0x0017
+#define IB_SMP_ATTR_VL_ARB_TABLE 0x0018
+#define IB_SMP_ATTR_LINEAR_FORWARD_TABLE 0x0019
+#define IB_SMP_ATTR_RANDOM_FORWARD_TABLE 0x001A
+#define IB_SMP_ATTR_MCAST_FORWARD_TABLE 0x001B
+#define IB_SMP_ATTR_SM_INFO 0x0020
+#define IB_SMP_ATTR_VENDOR_DIAG 0x0030
+#define IB_SMP_ATTR_LED_INFO 0x0031
+#define IB_SMP_ATTR_VENDOR_MASK 0xFF00
+
+#define IB_SA_ATTR_MC_MEMBER_REC 0x38
+#define IB_SA_ATTR_PATH_REC 0x35
+
+#define IB_SA_MCMEMBER_REC_MGID (1<<0)
+#define IB_SA_MCMEMBER_REC_PORT_GID (1<<1)
+#define IB_SA_MCMEMBER_REC_QKEY (1<<2)
+#define IB_SA_MCMEMBER_REC_MLID (1<<3)
+#define IB_SA_MCMEMBER_REC_MTU_SELECTOR (1<<4)
+#define IB_SA_MCMEMBER_REC_MTU (1<<5)
+#define IB_SA_MCMEMBER_REC_TRAFFIC_CLASS (1<<6)
+#define IB_SA_MCMEMBER_REC_PKEY (1<<7)
+#define IB_SA_MCMEMBER_REC_RATE_SELECTOR (1<<8)
+#define IB_SA_MCMEMBER_REC_RATE (1<<9)
+#define IB_SA_MCMEMBER_REC_PACKET_LIFE_TIME_SELECTOR (1<<10)
+#define IB_SA_MCMEMBER_REC_PACKET_LIFE_TIME (1<<11)
+#define IB_SA_MCMEMBER_REC_SL (1<<12)
+#define IB_SA_MCMEMBER_REC_FLOW_LABEL (1<<13)
+#define IB_SA_MCMEMBER_REC_HOP_LIMIT (1<<14)
+#define IB_SA_MCMEMBER_REC_SCOPE (1<<15)
+#define IB_SA_MCMEMBER_REC_JOIN_STATE (1<<16)
+#define IB_SA_MCMEMBER_REC_PROXY_JOIN (1<<17)
+
+#define IB_SA_PATH_REC_DGID (1<<2)
+#define IB_SA_PATH_REC_SGID (1<<3)
+
+struct ib_mad_hdr {
+ uint8_t base_version;
+ uint8_t mgmt_class;
+ uint8_t class_version;
+ uint8_t method;
+ uint16_t status;
+ uint16_t class_specific;
+ uint32_t tid[2];
+ uint16_t attr_id;
+ uint16_t resv;
+ uint32_t attr_mod;
+} __attribute__ (( packed ));
+
+struct ib_sa_hdr {
+ uint32_t sm_key[2];
+ uint16_t reserved;
+ uint16_t attrib_offset;
+ uint32_t comp_mask[2];
+} __attribute__ (( packed ));
+
+struct ib_rmpp_hdr {
+ uint32_t raw[3];
+} __attribute__ (( packed ));
+
+struct ib_mad_data {
+ struct ib_mad_hdr mad_hdr;
+ uint8_t data[232];
+} __attribute__ (( packed ));
+
+struct ib_mad_guid_info {
+ struct ib_mad_hdr mad_hdr;
+ uint32_t mkey[2];
+ uint32_t reserved[8];
+ uint8_t gid_local[8];
+} __attribute__ (( packed ));
+
+struct ib_mad_port_info {
+ struct ib_mad_hdr mad_hdr;
+ uint32_t mkey[2];
+ uint32_t reserved[8];
+ uint32_t mkey2[2];
+ uint8_t gid_prefix[8];
+ uint16_t lid;
+ uint16_t mastersm_lid;
+ uint32_t cap_mask;
+ uint16_t diag_code;
+ uint16_t mkey_lease_period;
+ uint8_t local_port_num;
+ uint8_t link_width_enabled;
+ uint8_t link_width_supported;
+ uint8_t link_width_active;
+ uint8_t port_state__link_speed_supported;
+ uint8_t link_down_def_state__port_phys_state;
+ uint8_t lmc__r1__mkey_prot_bits;
+ uint8_t link_speed_enabled__link_speed_active;
+} __attribute__ (( packed ));
+
+struct ib_mad_pkey_table {
+ struct ib_mad_hdr mad_hdr;
+ uint32_t mkey[2];
+ uint32_t reserved[8];
+ uint16_t pkey[16][2];
+} __attribute__ (( packed ));
+
+struct ib_mad_path_record {
+ struct ib_mad_hdr mad_hdr;
+ struct ib_rmpp_hdr rmpp_hdr;
+ struct ib_sa_hdr sa_hdr;
+ uint32_t reserved0[2];
+ struct ib_gid dgid;
+ struct ib_gid sgid;
+ uint16_t dlid;
+ uint16_t slid;
+ uint32_t hop_limit__flow_label__raw_traffic;
+ uint32_t pkey__numb_path__reversible__tclass;
+ uint8_t reserved1;
+ uint8_t reserved__sl;
+ uint8_t mtu_selector__mtu;
+ uint8_t rate_selector__rate;
+ uint32_t preference__packet_lifetime__packet_lifetime_selector;
+ uint32_t reserved2[35];
+} __attribute__ (( packed ));
+
+struct ib_mad_mc_member_record {
+ struct ib_mad_hdr mad_hdr;
+ struct ib_rmpp_hdr rmpp_hdr;
+ struct ib_sa_hdr sa_hdr;
+ struct ib_gid mgid;
+ struct ib_gid port_gid;
+ uint32_t qkey;
+ uint16_t mlid;
+ uint8_t mtu_selector__mtu;
+ uint8_t tclass;
+ uint16_t pkey;
+ uint8_t rate_selector__rate;
+ uint8_t packet_lifetime_selector__packet_lifetime;
+ uint32_t sl__flow_label__hop_limit;
+ uint8_t scope__join_state;
+ uint8_t proxy_join__reserved;
+ uint16_t reserved0;
+ uint32_t reserved1[37];
+} __attribute__ (( packed ));
+
+union ib_mad {
+ struct ib_mad_hdr mad_hdr;
+ struct ib_mad_data data;
+ struct ib_mad_guid_info guid_info;
+ struct ib_mad_port_info port_info;
+ struct ib_mad_pkey_table pkey_table;
+ struct ib_mad_path_record path_record;
+ struct ib_mad_mc_member_record mc_member_record;
+} __attribute__ (( packed ));
+
+#endif /* _GPXE_INFINIBAND_H */
diff --git a/gpxe/src/include/gpxe/init.h b/gpxe/src/include/gpxe/init.h
new file mode 100644
index 00000000..d83aa5e5
--- /dev/null
+++ b/gpxe/src/include/gpxe/init.h
@@ -0,0 +1,62 @@
+#ifndef _GPXE_INIT_H
+#define _GPXE_INIT_H
+
+#include <gpxe/tables.h>
+
+/**
+ * An initialisation function
+ *
+ * Initialisation functions are called exactly once, as part of the
+ * call to initialise().
+ */
+struct init_fn {
+ void ( * initialise ) ( void );
+};
+
+/** Declare an initialisation functon */
+#define __init_fn( init_order ) \
+ __table ( struct init_fn, init_fns, init_order )
+
+/** @defgroup initfn_order Initialisation function ordering
+ * @{
+ */
+
+#define INIT_EARLY 01 /**< Early initialisation */
+#define INIT_CONSOLE 02 /**< Console initialisation */
+#define INIT_NORMAL 03 /**< Normal initialisation */
+
+/** @} */
+
+/**
+ * A startup/shutdown function
+ *
+ * Startup and shutdown functions may be called multiple times, as
+ * part of the calls to startup() and shutdown().
+ */
+struct startup_fn {
+ void ( * startup ) ( void );
+ void ( * shutdown ) ( void );
+};
+
+/** Declare a startup/shutdown function */
+#define __startup_fn( startup_order ) \
+ __table ( struct startup_fn, startup_fns, startup_order )
+
+/** @defgroup startfn_order Startup/shutdown function ordering
+ *
+ * Shutdown functions are called in the reverse order to startup
+ * functions.
+ *
+ * @{
+ */
+
+#define STARTUP_EARLY 01 /**< Early startup */
+#define STARTUP_NORMAL 02 /**< Normal startup */
+
+/** @} */
+
+extern void initialise ( void );
+extern void startup ( void );
+extern void shutdown ( void );
+
+#endif /* _GPXE_INIT_H */
diff --git a/gpxe/src/include/gpxe/initrd.h b/gpxe/src/include/gpxe/initrd.h
new file mode 100644
index 00000000..1871bf78
--- /dev/null
+++ b/gpxe/src/include/gpxe/initrd.h
@@ -0,0 +1,14 @@
+#ifndef _GPXE_INITRD_H
+#define _GPXE_INITRD_H
+
+/**
+ * @file
+ *
+ * Linux initrd image format
+ *
+ */
+
+#include <gpxe/image.h>
+extern struct image_type initrd_image_type __image_type ( PROBE_NORMAL );
+
+#endif /* _GPXE_INITRD_H */
diff --git a/gpxe/src/include/gpxe/interface.h b/gpxe/src/include/gpxe/interface.h
new file mode 100644
index 00000000..94c711a9
--- /dev/null
+++ b/gpxe/src/include/gpxe/interface.h
@@ -0,0 +1,56 @@
+#ifndef _GPXE_INTERFACE_H
+#define _GPXE_INTERFACE_H
+
+/** @file
+ *
+ * Object communication interfaces
+ *
+ */
+
+#include <gpxe/refcnt.h>
+
+/** An object communication interface */
+struct interface {
+ /** Destination interface
+ *
+ * When messages are sent via this interface, they will be
+ * delivered to the destination interface.
+ *
+ * This pointer may never be NULL. When the interface is
+ * unplugged, it should point to a null interface.
+ */
+ struct interface *dest;
+ /** Reference counter
+ *
+ * If this interface is not part of a reference-counted
+ * object, this field may be NULL.
+ */
+ struct refcnt *refcnt;
+};
+
+/**
+ * Increment reference count on an interface
+ *
+ * @v intf Interface
+ * @ret intf Interface
+ */
+static inline __attribute__ (( always_inline )) struct interface *
+intf_get ( struct interface *intf ) {
+ ref_get ( intf->refcnt );
+ return intf;
+}
+
+/**
+ * Decrement reference count on an interface
+ *
+ * @v intf Interface
+ */
+static inline __attribute__ (( always_inline )) void
+intf_put ( struct interface *intf ) {
+ ref_put ( intf->refcnt );
+}
+
+extern void plug ( struct interface *intf, struct interface *dest );
+extern void plug_plug ( struct interface *a, struct interface *b );
+
+#endif /* _GPXE_INTERFACE_H */
diff --git a/gpxe/src/include/gpxe/iobuf.h b/gpxe/src/include/gpxe/iobuf.h
new file mode 100644
index 00000000..ff787754
--- /dev/null
+++ b/gpxe/src/include/gpxe/iobuf.h
@@ -0,0 +1,189 @@
+#ifndef _GPXE_IOBUF_H
+#define _GPXE_IOBUF_H
+
+/** @file
+ *
+ * I/O buffers
+ *
+ */
+
+#include <stdint.h>
+#include <assert.h>
+#include <gpxe/list.h>
+
+/**
+ * I/O buffer alignment
+ *
+ * I/O buffers allocated via alloc_iob() are guaranteed to be
+ * physically aligned to this boundary. Some cards cannot DMA across
+ * a 4kB boundary. With a standard Ethernet MTU, aligning to a 2kB
+ * boundary is sufficient to guarantee no 4kB boundary crossings. For
+ * a jumbo Ethernet MTU, a packet may be larger than 4kB anyway.
+ */
+#define IOB_ALIGN 2048
+
+/**
+ * Minimum I/O buffer length
+ *
+ * alloc_iob() will round up the allocated length to this size if
+ * necessary. This is used on behalf of hardware that is not capable
+ * of auto-padding.
+ */
+#define IOB_ZLEN 64
+
+/**
+ * A persistent I/O buffer
+ *
+ * This data structure encapsulates a long-lived I/O buffer. The
+ * buffer may be passed between multiple owners, queued for possible
+ * retransmission, etc.
+ */
+struct io_buffer {
+ /** List of which this buffer is a member
+ *
+ * The list must belong to the current owner of the buffer.
+ * Different owners may maintain different lists (e.g. a
+ * retransmission list for TCP).
+ */
+ struct list_head list;
+
+ /** Start of the buffer */
+ void *head;
+ /** Start of data */
+ void *data;
+ /** End of data */
+ void *tail;
+ /** End of the buffer */
+ void *end;
+};
+
+/**
+ * Reserve space at start of I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @v len Length to reserve
+ * @ret data Pointer to new start of buffer
+ */
+static inline void * iob_reserve ( struct io_buffer *iobuf, size_t len ) {
+ iobuf->data += len;
+ iobuf->tail += len;
+ return iobuf->data;
+}
+#define iob_reserve( iobuf, len ) ( { \
+ void *__result; \
+ __result = iob_reserve ( (iobuf), (len) ); \
+ assert ( (iobuf)->tail <= (iobuf)->end ); \
+ __result; } )
+
+/**
+ * Add data to start of I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @v len Length to add
+ * @ret data Pointer to new start of buffer
+ */
+static inline void * iob_push ( struct io_buffer *iobuf, size_t len ) {
+ iobuf->data -= len;
+ return iobuf->data;
+}
+#define iob_push( iobuf, len ) ( { \
+ void *__result; \
+ __result = iob_push ( (iobuf), (len) ); \
+ assert ( (iobuf)->data >= (iobuf)->head ); \
+ __result; } )
+
+/**
+ * Remove data from start of I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @v len Length to remove
+ * @ret data Pointer to new start of buffer
+ */
+static inline void * iob_pull ( struct io_buffer *iobuf, size_t len ) {
+ iobuf->data += len;
+ assert ( iobuf->data <= iobuf->tail );
+ return iobuf->data;
+}
+#define iob_pull( iobuf, len ) ( { \
+ void *__result; \
+ __result = iob_pull ( (iobuf), (len) ); \
+ assert ( (iobuf)->data <= (iobuf)->tail ); \
+ __result; } )
+
+/**
+ * Add data to end of I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @v len Length to add
+ * @ret data Pointer to newly added space
+ */
+static inline void * iob_put ( struct io_buffer *iobuf, size_t len ) {
+ void *old_tail = iobuf->tail;
+ iobuf->tail += len;
+ return old_tail;
+}
+#define iob_put( iobuf, len ) ( { \
+ void *__result; \
+ __result = iob_put ( (iobuf), (len) ); \
+ assert ( (iobuf)->tail <= (iobuf)->end ); \
+ __result; } )
+
+/**
+ * Remove data from end of I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @v len Length to remove
+ */
+static inline void iob_unput ( struct io_buffer *iobuf, size_t len ) {
+ iobuf->tail -= len;
+}
+#define iob_unput( iobuf, len ) do { \
+ iob_unput ( (iobuf), (len) ); \
+ assert ( (iobuf)->tail >= (iobuf)->data ); \
+ } while ( 0 )
+
+/**
+ * Empty an I/O buffer
+ *
+ * @v iobuf I/O buffer
+ */
+static inline void iob_empty ( struct io_buffer *iobuf ) {
+ iobuf->tail = iobuf->data;
+}
+
+/**
+ * Calculate length of data in an I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @ret len Length of data in buffer
+ */
+static inline size_t iob_len ( struct io_buffer *iobuf ) {
+ return ( iobuf->tail - iobuf->data );
+}
+
+/**
+ * Calculate available space at start of an I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @ret len Length of data available at start of buffer
+ */
+static inline size_t iob_headroom ( struct io_buffer *iobuf ) {
+ return ( iobuf->data - iobuf->head );
+}
+
+/**
+ * Calculate available space at end of an I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @ret len Length of data available at end of buffer
+ */
+static inline size_t iob_tailroom ( struct io_buffer *iobuf ) {
+ return ( iobuf->end - iobuf->tail );
+}
+
+extern struct io_buffer * __malloc alloc_iob ( size_t len );
+extern void free_iob ( struct io_buffer *iobuf );
+extern void iob_pad ( struct io_buffer *iobuf, size_t min_len );
+extern int iob_ensure_headroom ( struct io_buffer *iobuf, size_t len );
+
+#endif /* _GPXE_IOBUF_H */
diff --git a/gpxe/src/include/gpxe/ip.h b/gpxe/src/include/gpxe/ip.h
new file mode 100644
index 00000000..b1b0c48c
--- /dev/null
+++ b/gpxe/src/include/gpxe/ip.h
@@ -0,0 +1,95 @@
+#ifndef _GPXE_IP_H
+#define _GPXE_IP_H
+
+/** @file
+ *
+ * IP protocol
+ *
+ */
+
+#include <stdint.h>
+#include <gpxe/in.h>
+#include <gpxe/list.h>
+#include <gpxe/retry.h>
+
+struct io_buffer;
+struct net_device;
+struct net_protocol;
+
+/* IP constants */
+
+#define IP_VER 0x40U
+#define IP_MASK_VER 0xf0U
+#define IP_MASK_HLEN 0x0fU
+#define IP_MASK_OFFSET 0x1fffU
+#define IP_MASK_DONOTFRAG 0x4000U
+#define IP_MASK_MOREFRAGS 0x2000U
+#define IP_PSHLEN 12
+
+/* IP header defaults */
+#define IP_TOS 0
+#define IP_TTL 64
+
+#define IP_FRAG_IOB_SIZE 1500
+#define IP_FRAG_TIMEOUT 50
+
+/** An IPv4 packet header */
+struct iphdr {
+ uint8_t verhdrlen;
+ uint8_t service;
+ uint16_t len;
+ uint16_t ident;
+ uint16_t frags;
+ uint8_t ttl;
+ uint8_t protocol;
+ uint16_t chksum;
+ struct in_addr src;
+ struct in_addr dest;
+} __attribute__ (( packed ));
+
+/** An IPv4 pseudo header */
+struct ipv4_pseudo_header {
+ struct in_addr src;
+ struct in_addr dest;
+ uint8_t zero_padding;
+ uint8_t protocol;
+ uint16_t len;
+};
+
+/** An IPv4 address/routing table entry */
+struct ipv4_miniroute {
+ /** List of miniroutes */
+ struct list_head list;
+
+ /** Network device */
+ struct net_device *netdev;
+
+ /** IPv4 address */
+ struct in_addr address;
+ /** Subnet mask */
+ struct in_addr netmask;
+ /** Gateway address */
+ struct in_addr gateway;
+};
+
+/* Fragment reassembly buffer */
+struct frag_buffer {
+ /* Identification number */
+ uint16_t ident;
+ /* Source network address */
+ struct in_addr src;
+ /* Destination network address */
+ struct in_addr dest;
+ /* Reassembled I/O buffer */
+ struct io_buffer *frag_iob;
+ /* Reassembly timer */
+ struct retry_timer frag_timer;
+ /* List of fragment reassembly buffers */
+ struct list_head list;
+};
+
+extern struct list_head ipv4_miniroutes;
+
+extern struct net_protocol ipv4_protocol;
+
+#endif /* _GPXE_IP_H */
diff --git a/gpxe/src/include/gpxe/ip6.h b/gpxe/src/include/gpxe/ip6.h
new file mode 100644
index 00000000..dc0ae31f
--- /dev/null
+++ b/gpxe/src/include/gpxe/ip6.h
@@ -0,0 +1,78 @@
+#ifndef _GPXE_IP6_H
+#define _GPXE_IP6_H
+
+/** @file
+ *
+ * IP6 protocol
+ *
+ */
+
+#include <stdint.h>
+#include <gpxe/in.h>
+
+/* IP6 constants */
+
+#define IP6_VERSION 0x6
+#define IP6_HOP_LIMIT 255
+
+/**
+ * I/O buffer contents
+ * This is duplicated in tcp.h and here. Ideally it should go into iobuf.h
+ */
+#define MAX_HDR_LEN 100
+#define MAX_IOB_LEN 1500
+#define MIN_IOB_LEN MAX_HDR_LEN + 100 /* To account for padding by LL */
+
+#define IP6_EQUAL( in6_addr1, in6_addr2 ) \
+ ( memcmp ( ( char* ) &( in6_addr1 ), ( char* ) &( in6_addr2 ),\
+ sizeof ( struct in6_addr ) ) == 0 )
+
+#define IS_UNSPECIFIED( addr ) \
+ ( ( (addr).in6_u.u6_addr32[0] == 0x00000000 ) && \
+ ( (addr).in6_u.u6_addr32[1] == 0x00000000 ) && \
+ ( (addr).in6_u.u6_addr32[2] == 0x00000000 ) && \
+ ( (addr).in6_u.u6_addr32[3] == 0x00000000 ) )
+/* IP6 header */
+struct ip6_header {
+ uint32_t ver_traffic_class_flow_label;
+ uint16_t payload_len;
+ uint8_t nxt_hdr;
+ uint8_t hop_limit;
+ struct in6_addr src;
+ struct in6_addr dest;
+};
+
+/* IP6 pseudo header */
+struct ipv6_pseudo_header {
+ struct in6_addr src;
+ struct in6_addr dest;
+ uint8_t zero_padding;
+ uint8_t nxt_hdr;
+ uint16_t len;
+};
+
+/* Next header numbers */
+#define IP6_HOPBYHOP 0x00
+#define IP6_ROUTING 0x43
+#define IP6_FRAGMENT 0x44
+#define IP6_AUTHENTICATION 0x51
+#define IP6_DEST_OPTS 0x60
+#define IP6_ESP 0x50
+#define IP6_ICMP6 0x58
+#define IP6_NO_HEADER 0x59
+
+struct io_buffer;
+struct net_device;
+struct net_protocol;
+
+extern struct net_protocol ipv6_protocol;
+extern struct tcpip_net_protocol ipv6_tcpip_protocol;
+extern char * inet6_ntoa ( struct in6_addr in6 );
+
+extern int add_ipv6_address ( struct net_device *netdev,
+ struct in6_addr prefix, int prefix_len,
+ struct in6_addr address,
+ struct in6_addr gateway );
+extern void del_ipv6_address ( struct net_device *netdev );
+
+#endif /* _GPXE_IP6_H */
diff --git a/gpxe/src/include/gpxe/ipoib.h b/gpxe/src/include/gpxe/ipoib.h
new file mode 100644
index 00000000..0551687d
--- /dev/null
+++ b/gpxe/src/include/gpxe/ipoib.h
@@ -0,0 +1,78 @@
+#ifndef _GPXE_IPOIB_H
+#define _GPXE_IPOIB_H
+
+/** @file
+ *
+ * IP over Infiniband
+ */
+
+#include <gpxe/infiniband.h>
+
+/** IPoIB MAC address length */
+#define IPOIB_ALEN 20
+
+/** An IPoIB MAC address */
+struct ipoib_mac {
+ /** Queue pair number
+ *
+ * MSB must be zero; QPNs are only 24-bit.
+ */
+ uint32_t qpn;
+ /** Port GID */
+ struct ib_gid gid;
+} __attribute__ (( packed ));
+
+/** IPoIB link-layer header length */
+#define IPOIB_HLEN 24
+
+/**
+ * IPoIB link-layer header pseudo portion
+ *
+ * This part doesn't actually exist on the wire, but it provides a
+ * convenient way to fit into the typical network device model.
+ */
+struct ipoib_pseudo_hdr {
+ /** Peer address */
+ struct ipoib_mac peer;
+} __attribute__ (( packed ));
+
+/** IPoIB link-layer header real portion */
+struct ipoib_real_hdr {
+ /** Network-layer protocol */
+ uint16_t proto;
+ /** Reserved, must be zero */
+ uint16_t reserved;
+} __attribute__ (( packed ));
+
+/** An IPoIB link-layer header */
+struct ipoib_hdr {
+ /** Pseudo portion */
+ struct ipoib_pseudo_hdr pseudo;
+ /** Real portion */
+ struct ipoib_real_hdr real;
+} __attribute__ (( packed ));
+
+extern struct ll_protocol ipoib_protocol;
+
+extern const char * ipoib_ntoa ( const void *ll_addr );
+
+/**
+ * Allocate IPoIB device
+ *
+ * @v priv_size Size of driver private data
+ * @ret netdev Network device, or NULL
+ */
+static inline struct net_device * alloc_ipoibdev ( size_t priv_size ) {
+ struct net_device *netdev;
+
+ netdev = alloc_netdev ( priv_size );
+ if ( netdev ) {
+ netdev->ll_protocol = &ipoib_protocol;
+ }
+ return netdev;
+}
+
+extern int ipoib_probe ( struct ib_device *ibdev );
+extern void ipoib_remove ( struct ib_device *ibdev );
+
+#endif /* _GPXE_IPOIB_H */
diff --git a/gpxe/src/include/gpxe/isa.h b/gpxe/src/include/gpxe/isa.h
new file mode 100644
index 00000000..bb25dbce
--- /dev/null
+++ b/gpxe/src/include/gpxe/isa.h
@@ -0,0 +1,92 @@
+#ifndef ISA_H
+#define ISA_H
+
+#include <stdint.h>
+#include <gpxe/isa_ids.h>
+#include <gpxe/device.h>
+#include <gpxe/tables.h>
+
+/** An ISA device */
+struct isa_device {
+ /** Generic device */
+ struct device dev;
+ /** I/O address */
+ uint16_t ioaddr;
+ /** Driver for this device */
+ struct isa_driver *driver;
+ /** Driver-private data
+ *
+ * Use isa_set_drvdata() and isa_get_drvdata() to access
+ * this field.
+ */
+ void *priv;
+ /** Driver name */
+ const char *driver_name;
+};
+
+/*
+ * An individual ISA device, identified by probe address
+ *
+ */
+typedef uint16_t isa_probe_addr_t;
+
+/** An ISA driver */
+struct isa_driver {
+ /** Name */
+ const char *name;
+ /** Probe address list */
+ isa_probe_addr_t *probe_addrs;
+ /** Number of entries in probe address list */
+ unsigned int addr_count;
+ /** Manufacturer ID to be assumed for this device */
+ uint16_t vendor_id;
+ /** Product ID to be assumed for this device */
+ uint16_t prod_id;
+ /**
+ * Probe device
+ *
+ * @v isa ISA device
+ * @v id Matching entry in ID table
+ * @ret rc Return status code
+ */
+ int ( * probe ) ( struct isa_device *isa );
+ /**
+ * Remove device
+ *
+ * @v isa ISA device
+ */
+ void ( * remove ) ( struct isa_device *isa );
+};
+
+/** Declare an ISA driver */
+#define __isa_driver __table ( struct isa_driver, isa_drivers, 01 )
+
+/**
+ * Set ISA driver-private data
+ *
+ * @v isa ISA device
+ * @v priv Private data
+ */
+static inline void isa_set_drvdata ( struct isa_device *isa, void *priv ) {
+ isa->priv = priv;
+}
+
+/**
+ * Get ISA driver-private data
+ *
+ * @v isa ISA device
+ * @ret priv Private data
+ */
+static inline void * isa_get_drvdata ( struct isa_device *isa ) {
+ return isa->priv;
+}
+
+/*
+ * ISA_ROM is parsed by parserom.pl to generate Makefile rules and
+ * files for rom-o-matic.
+ *
+ */
+#define ISA_ROM( IMAGE, DESCRIPTION )
+
+#endif /* ISA_H */
+
diff --git a/gpxe/src/include/gpxe/isa_ids.h b/gpxe/src/include/gpxe/isa_ids.h
new file mode 100644
index 00000000..bf3f1015
--- /dev/null
+++ b/gpxe/src/include/gpxe/isa_ids.h
@@ -0,0 +1,49 @@
+#ifndef ISA_IDS_H
+#define ISA_IDS_H
+
+/*
+ * This file defines IDs as used by ISAPnP and EISA devices. These
+ * IDs have the format:
+ *
+ * vendor byte 0 bit 7 must be zero
+ * bits 6-2 first vendor char in compressed ASCII
+ * bits 1-0 second vendor char in compressed ASCII (bits 4-3)
+ * byte 1 bits 7-5 second vendor char in compressed ASCII (bits 2-0)
+ * bits 4-0 third vendor char in compressed ASCII
+ * product byte 0 bits 7-4 first hex digit of product number
+ * bits 3-0 second hex digit of product number
+ * byte 1 bits 7-4 third hex digit of product number
+ * bits 3-0 hex digit of revision level
+ *
+ * ISA IDs are always expressed in little-endian order, even though
+ * the underlying "meaning" is big-endian.
+ */
+
+#include <byteswap.h>
+
+/*
+ * Construct a vendor ID from three ASCII characters
+ *
+ */
+#define ISA_VENDOR( a, b, c ) \
+ bswap_16 ( ( ( ( (a) - 'A' + 1 ) & 0x1f ) << 10 ) | \
+ ( ( ( (b) - 'A' + 1 ) & 0x1f ) << 5 ) | \
+ ( ( ( (c) - 'A' + 1 ) & 0x1f ) << 0 ) )
+
+#define ISAPNP_VENDOR( a, b, c ) ISA_VENDOR ( a, b, c )
+#define EISA_VENDOR( a, b, c ) ISA_VENDOR ( a, b, c )
+
+#define GENERIC_ISAPNP_VENDOR ISAPNP_VENDOR ( 'P','N','P' )
+
+/*
+ * Extract product ID and revision from combined product field
+ *
+ */
+#define ISA_PROD_ID_MASK ( 0xf0ff )
+#define ISA_PROD_ID(product) ( (product) & ISA_PROD_ID_MASK )
+#define ISA_PROD_REV(product) ( ( (product) & ~ISA_PROD_ID_MASK ) >> 8 )
+
+/* Functions in isa_ids.c */
+extern char * isa_id_string ( unsigned int vendor, unsigned int product );
+
+#endif /* ISA_IDS_H */
diff --git a/gpxe/src/include/gpxe/isapnp.h b/gpxe/src/include/gpxe/isapnp.h
new file mode 100644
index 00000000..07797a99
--- /dev/null
+++ b/gpxe/src/include/gpxe/isapnp.h
@@ -0,0 +1,273 @@
+/**************************************************************************
+*
+* isapnp.h -- Etherboot isapnp support for the 3Com 3c515
+* Written 2002-2003 by Timothy Legge <tlegge@rogers.com>
+*
+* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Portions of this code:
+* Copyright (C) 2001 P.J.H.Fox (fox@roestock.demon.co.uk)
+*
+*
+*
+* REVISION HISTORY:
+* ================
+* Version 0.1 April 26, 2002 TJL
+* Version 0.2 01/08/2003 TJL Renamed from 3c515_isapnp.h
+*
+*
+* Generalised into an ISAPnP bus that can be used by more than just
+* the 3c515 by Michael Brown <mbrown@fensystems.co.uk>
+*
+***************************************************************************/
+
+#ifndef ISAPNP_H
+#define ISAPNP_H
+
+#include <stdint.h>
+#include <gpxe/isa_ids.h>
+#include <gpxe/device.h>
+#include <gpxe/tables.h>
+
+/*
+ * ISAPnP constants
+ *
+ */
+
+/* Port addresses */
+#define ISAPNP_ADDRESS 0x279
+#define ISAPNP_WRITE_DATA 0xa79
+#define ISAPNP_READ_PORT_MIN 0x203
+#define ISAPNP_READ_PORT_START 0x213 /* ISAPnP spec says 0x203, but
+ * Linux ISAPnP starts at
+ * 0x213 with no explanatory
+ * comment. 0x203 probably
+ * clashes with something. */
+#define ISAPNP_READ_PORT_MAX 0x3ff
+#define ISAPNP_READ_PORT_STEP 0x10 /* Can be any multiple of 4
+ * according to the spec, but
+ * since ISA I/O addresses are
+ * allocated in blocks of 16,
+ * it makes no sense to use
+ * any value less than 16.
+ */
+
+/* Card select numbers */
+#define ISAPNP_CSN_MIN 0x01
+#define ISAPNP_CSN_MAX 0x0f
+
+/* Registers */
+#define ISAPNP_READPORT 0x00
+#define ISAPNP_SERIALISOLATION 0x01
+#define ISAPNP_CONFIGCONTROL 0x02
+#define ISAPNP_WAKE 0x03
+#define ISAPNP_RESOURCEDATA 0x04
+#define ISAPNP_STATUS 0x05
+#define ISAPNP_CARDSELECTNUMBER 0x06
+#define ISAPNP_LOGICALDEVICENUMBER 0x07
+#define ISAPNP_ACTIVATE 0x30
+#define ISAPNP_IORANGECHECK 0x31
+#define ISAPNP_IOBASE(n) ( 0x60 + ( (n) * 2 ) )
+#define ISAPNP_IRQNO(n) ( 0x70 + ( (n) * 2 ) )
+#define ISAPNP_IRQTYPE(n) ( 0x71 + ( (n) * 2 ) )
+
+/* Bits in the CONFIGCONTROL register */
+#define ISAPNP_CONFIG_RESET ( 1 << 0 )
+#define ISAPNP_CONFIG_WAIT_FOR_KEY ( 1 << 1 )
+#define ISAPNP_CONFIG_RESET_CSN ( 1 << 2 )
+#define ISAPNP_CONFIG_RESET_DRV ( ISAPNP_CONFIG_RESET | \
+ ISAPNP_CONFIG_WAIT_FOR_KEY | \
+ ISAPNP_CONFIG_RESET_CSN )
+
+/* The LFSR used for the initiation key and for checksumming */
+#define ISAPNP_LFSR_SEED 0x6a
+
+/* Small tags */
+#define ISAPNP_IS_SMALL_TAG(tag) ( ! ( (tag) & 0x80 ) )
+#define ISAPNP_SMALL_TAG_NAME(tag) ( ( (tag) >> 3 ) & 0xf )
+#define ISAPNP_SMALL_TAG_LEN(tag) ( ( (tag) & 0x7 ) )
+#define ISAPNP_TAG_PNPVERNO 0x01
+#define ISAPNP_TAG_LOGDEVID 0x02
+#define ISAPNP_TAG_COMPATDEVID 0x03
+#define ISAPNP_TAG_IRQ 0x04
+#define ISAPNP_TAG_DMA 0x05
+#define ISAPNP_TAG_STARTDEP 0x06
+#define ISAPNP_TAG_ENDDEP 0x07
+#define ISAPNP_TAG_IOPORT 0x08
+#define ISAPNP_TAG_FIXEDIO 0x09
+#define ISAPNP_TAG_RSVDSHORTA 0x0A
+#define ISAPNP_TAG_RSVDSHORTB 0x0B
+#define ISAPNP_TAG_RSVDSHORTC 0x0C
+#define ISAPNP_TAG_RSVDSHORTD 0x0D
+#define ISAPNP_TAG_VENDORSHORT 0x0E
+#define ISAPNP_TAG_END 0x0F
+/* Large tags */
+#define ISAPNP_IS_LARGE_TAG(tag) ( ( (tag) & 0x80 ) )
+#define ISAPNP_LARGE_TAG_NAME(tag) (tag)
+#define ISAPNP_TAG_MEMRANGE 0x81
+#define ISAPNP_TAG_ANSISTR 0x82
+#define ISAPNP_TAG_UNICODESTR 0x83
+#define ISAPNP_TAG_VENDORLONG 0x84
+#define ISAPNP_TAG_MEM32RANGE 0x85
+#define ISAPNP_TAG_FIXEDMEM32RANGE 0x86
+#define ISAPNP_TAG_RSVDLONG0 0xF0
+#define ISAPNP_TAG_RSVDLONG1 0xF1
+#define ISAPNP_TAG_RSVDLONG2 0xF2
+#define ISAPNP_TAG_RSVDLONG3 0xF3
+#define ISAPNP_TAG_RSVDLONG4 0xF4
+#define ISAPNP_TAG_RSVDLONG5 0xF5
+#define ISAPNP_TAG_RSVDLONG6 0xF6
+#define ISAPNP_TAG_RSVDLONG7 0xF7
+#define ISAPNP_TAG_RSVDLONG8 0xF8
+#define ISAPNP_TAG_RSVDLONG9 0xF9
+#define ISAPNP_TAG_RSVDLONGA 0xFA
+#define ISAPNP_TAG_RSVDLONGB 0xFB
+#define ISAPNP_TAG_RSVDLONGC 0xFC
+#define ISAPNP_TAG_RSVDLONGD 0xFD
+#define ISAPNP_TAG_RSVDLONGE 0xFE
+#define ISAPNP_TAG_RSVDLONGF 0xFF
+#define ISAPNP_TAG_PSEUDO_NEWBOARD 0x100
+
+/** An ISAPnP serial identifier */
+struct isapnp_identifier {
+ /** Vendor ID */
+ uint16_t vendor_id;
+ /** Product ID */
+ uint16_t prod_id;
+ /** Serial number */
+ uint32_t serial;
+ /** Checksum */
+ uint8_t checksum;
+} __attribute__ (( packed ));
+
+/** An ISAPnP logical device ID structure */
+struct isapnp_logdevid {
+ /** Vendor ID */
+ uint16_t vendor_id;
+ /** Product ID */
+ uint16_t prod_id;
+ /** Flags */
+ uint16_t flags;
+} __attribute__ (( packed ));
+
+/** An ISAPnP device ID list entry */
+struct isapnp_device_id {
+ /** Name */
+ const char *name;
+ /** Vendor ID */
+ uint16_t vendor_id;
+ /** Product ID */
+ uint16_t prod_id;
+};
+
+/** An ISAPnP device */
+struct isapnp_device {
+ /** Generic device */
+ struct device dev;
+ /** Vendor ID */
+ uint16_t vendor_id;
+ /** Product ID */
+ uint16_t prod_id;
+ /** I/O address */
+ uint16_t ioaddr;
+ /** Interrupt number */
+ uint8_t irqno;
+ /** Card Select Number */
+ uint8_t csn;
+ /** Logical Device ID */
+ uint8_t logdev;
+ /** Driver for this device */
+ struct isapnp_driver *driver;
+ /** Driver-private data
+ *
+ * Use isapnp_set_drvdata() and isapnp_get_drvdata() to access
+ * this field.
+ */
+ void *priv;
+ /** Driver name */
+ const char *driver_name;
+};
+
+/** An ISAPnP driver */
+struct isapnp_driver {
+ /** ISAPnP ID table */
+ struct isapnp_device_id *ids;
+ /** Number of entries in ISAPnP ID table */
+ unsigned int id_count;
+ /**
+ * Probe device
+ *
+ * @v isapnp ISAPnP device
+ * @v id Matching entry in ID table
+ * @ret rc Return status code
+ */
+ int ( * probe ) ( struct isapnp_device *isapnp,
+ const struct isapnp_device_id *id );
+ /**
+ * Remove device
+ *
+ * @v isapnp ISAPnP device
+ */
+ void ( * remove ) ( struct isapnp_device *isapnp );
+};
+
+/** Declare an ISAPnP driver */
+#define __isapnp_driver __table ( struct isapnp_driver, isapnp_drivers, 01 )
+
+extern uint16_t isapnp_read_port;
+
+extern void isapnp_device_activation ( struct isapnp_device *isapnp,
+ int activation );
+
+/**
+ * Activate ISAPnP device
+ *
+ * @v isapnp ISAPnP device
+ */
+static inline void activate_isapnp_device ( struct isapnp_device *isapnp ) {
+ isapnp_device_activation ( isapnp, 1 );
+}
+
+/**
+ * Deactivate ISAPnP device
+ *
+ * @v isapnp ISAPnP device
+ */
+static inline void deactivate_isapnp_device ( struct isapnp_device *isapnp ) {
+ isapnp_device_activation ( isapnp, 0 );
+}
+
+/**
+ * Set ISAPnP driver-private data
+ *
+ * @v isapnp ISAPnP device
+ * @v priv Private data
+ */
+static inline void isapnp_set_drvdata ( struct isapnp_device *isapnp,
+ void *priv ) {
+ isapnp->priv = priv;
+}
+
+/**
+ * Get ISAPnP driver-private data
+ *
+ * @v isapnp ISAPnP device
+ * @ret priv Private data
+ */
+static inline void * isapnp_get_drvdata ( struct isapnp_device *isapnp ) {
+ return isapnp->priv;
+}
+
+#endif /* ISAPNP_H */
diff --git a/gpxe/src/include/gpxe/iscsi.h b/gpxe/src/include/gpxe/iscsi.h
new file mode 100644
index 00000000..e4df6849
--- /dev/null
+++ b/gpxe/src/include/gpxe/iscsi.h
@@ -0,0 +1,654 @@
+#ifndef _GPXE_ISCSI_H
+#define _GPXE_ISCSI_H
+
+/** @file
+ *
+ * iSCSI protocol
+ *
+ */
+
+#include <stdint.h>
+#include <gpxe/socket.h>
+#include <gpxe/scsi.h>
+#include <gpxe/chap.h>
+#include <gpxe/refcnt.h>
+#include <gpxe/xfer.h>
+#include <gpxe/process.h>
+
+/** Default iSCSI port */
+#define ISCSI_PORT 3260
+
+/**
+ * iSCSI segment lengths
+ *
+ * iSCSI uses an icky structure with one one-byte field (a dword
+ * count) and one three-byte field (a byte count). This structure,
+ * and the accompanying macros, relieve some of the pain.
+ */
+union iscsi_segment_lengths {
+ struct {
+ /** The AHS length (measured in dwords) */
+ uint8_t ahs_len;
+ /** The data length (measured in bytes), in network
+ * byte order
+ */
+ uint8_t data_len[3];
+ } bytes;
+ /** Ths data length (measured in bytes), in network byte
+ * order, with ahs_len as the first byte.
+ */
+ uint32_t ahs_and_data_len;
+};
+
+/** The length of the additional header segment, in dwords */
+#define ISCSI_AHS_LEN( segment_lengths ) \
+ ( (segment_lengths).bytes.ahs_len )
+
+/** The length of the data segment, in bytes, excluding any padding */
+#define ISCSI_DATA_LEN( segment_lengths ) \
+ ( ntohl ( (segment_lengths).ahs_and_data_len ) & 0xffffff )
+
+/** The padding of the data segment, in bytes */
+#define ISCSI_DATA_PAD_LEN( segment_lengths ) \
+ ( ( 0 - (segment_lengths).bytes.data_len[2] ) & 0x03 )
+
+/** Set additional header and data segment lengths */
+#define ISCSI_SET_LENGTHS( segment_lengths, ahs_len, data_len ) do { \
+ (segment_lengths).ahs_and_data_len = \
+ htonl ( data_len | ( ahs_len << 24 ) ); \
+ } while ( 0 )
+
+/**
+ * iSCSI basic header segment common fields
+ *
+ */
+struct iscsi_bhs_common {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Fields specific to the PDU type */
+ uint8_t other_a[2];
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Fields specific to the PDU type */
+ uint8_t other_b[8];
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Fields specific to the PDU type */
+ uint8_t other_c[28];
+};
+
+/** Opcode mask */
+#define ISCSI_OPCODE_MASK 0x3f
+
+/** Immediate delivery */
+#define ISCSI_FLAG_IMMEDIATE 0x40
+
+/** Final PDU of a sequence */
+#define ISCSI_FLAG_FINAL 0x80
+
+/**
+ * iSCSI basic header segment common request fields
+ *
+ */
+struct iscsi_bhs_common_response {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Fields specific to the PDU type */
+ uint8_t other_a[2];
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Fields specific to the PDU type */
+ uint8_t other_b[8];
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Fields specific to the PDU type */
+ uint8_t other_c[4];
+ /** Status sequence number */
+ uint32_t statsn;
+ /** Expected command sequence number */
+ uint32_t expcmdsn;
+ /** Fields specific to the PDU type */
+ uint8_t other_d[16];
+};
+
+/**
+ * iSCSI login request basic header segment
+ *
+ */
+struct iscsi_bhs_login_request {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Maximum supported version number */
+ uint8_t version_max;
+ /** Minimum supported version number */
+ uint8_t version_min;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Initiator session ID (IANA format) enterprise number and flags */
+ uint32_t isid_iana_en;
+ /** Initiator session ID (IANA format) qualifier */
+ uint16_t isid_iana_qual;
+ /** Target session identifying handle */
+ uint16_t tsih;
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Connection ID */
+ uint16_t cid;
+ /** Reserved */
+ uint16_t reserved_a;
+ /** Command sequence number */
+ uint32_t cmdsn;
+ /** Expected status sequence number */
+ uint32_t expstatsn;
+ /** Reserved */
+ uint8_t reserved_b[16];
+};
+
+/** Login request opcode */
+#define ISCSI_OPCODE_LOGIN_REQUEST 0x03
+
+/** Willingness to transition to next stage */
+#define ISCSI_LOGIN_FLAG_TRANSITION 0x80
+
+/** Key=value pairs continued in subsequent request */
+#define ISCSI_LOGIN_FLAG_CONTINUE 0x40
+
+/* Current stage values and mask */
+#define ISCSI_LOGIN_CSG_MASK 0x0c
+#define ISCSI_LOGIN_CSG_SECURITY_NEGOTIATION 0x00
+#define ISCSI_LOGIN_CSG_OPERATIONAL_NEGOTIATION 0x04
+#define ISCSI_LOGIN_CSG_FULL_FEATURE_PHASE 0x0c
+
+/* Next stage values and mask */
+#define ISCSI_LOGIN_NSG_MASK 0x03
+#define ISCSI_LOGIN_NSG_SECURITY_NEGOTIATION 0x00
+#define ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION 0x01
+#define ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE 0x03
+
+/** ISID IANA format marker */
+#define ISCSI_ISID_IANA 0x40000000
+
+/** Fen Systems Ltd. IANA enterprise number
+ *
+ * Permission is hereby granted to use Fen Systems Ltd.'s IANA
+ * enterprise number with this iSCSI implementation.
+ */
+#define IANA_EN_FEN_SYSTEMS 10019
+
+/**
+ * iSCSI login response basic header segment
+ *
+ */
+struct iscsi_bhs_login_response {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Maximum supported version number */
+ uint8_t version_max;
+ /** Minimum supported version number */
+ uint8_t version_min;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Initiator session ID (IANA format) enterprise number and flags */
+ uint32_t isid_iana_en;
+ /** Initiator session ID (IANA format) qualifier */
+ uint16_t isid_iana_qual;
+ /** Target session identifying handle */
+ uint16_t tsih;
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Reserved */
+ uint32_t reserved_a;
+ /** Status sequence number */
+ uint32_t statsn;
+ /** Expected command sequence number */
+ uint32_t expcmdsn;
+ /** Maximum command sequence number */
+ uint32_t maxcmdsn;
+ /** Status class */
+ uint8_t status_class;
+ /** Status detail */
+ uint8_t status_detail;
+ /** Reserved */
+ uint8_t reserved_b[10];
+};
+
+/** Login response opcode */
+#define ISCSI_OPCODE_LOGIN_RESPONSE 0x23
+
+/* Login response status codes */
+#define ISCSI_STATUS_SUCCESS 0x00
+#define ISCSI_STATUS_REDIRECT 0x01
+#define ISCSI_STATUS_INITIATOR_ERROR 0x02
+#define ISCSI_STATUS_TARGET_ERROR 0x03
+
+/**
+ * iSCSI SCSI command basic header segment
+ *
+ */
+struct iscsi_bhs_scsi_command {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Reserved */
+ uint16_t reserved_a;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** SCSI Logical Unit Number */
+ uint64_t lun;
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Expected data transfer length */
+ uint32_t exp_len;
+ /** Command sequence number */
+ uint32_t cmdsn;
+ /** Expected status sequence number */
+ uint32_t expstatsn;
+ /** SCSI Command Descriptor Block (CDB) */
+ union scsi_cdb cdb;
+};
+
+/** SCSI command opcode */
+#define ISCSI_OPCODE_SCSI_COMMAND 0x01
+
+/** Command will read data */
+#define ISCSI_COMMAND_FLAG_READ 0x40
+
+/** Command will write data */
+#define ISCSI_COMMAND_FLAG_WRITE 0x20
+
+/* Task attributes */
+#define ISCSI_COMMAND_ATTR_UNTAGGED 0x00
+#define ISCSI_COMMAND_ATTR_SIMPLE 0x01
+#define ISCSI_COMMAND_ATTR_ORDERED 0x02
+#define ISCSI_COMMAND_ATTR_HEAD_OF_QUEUE 0x03
+#define ISCSI_COMMAND_ATTR_ACA 0x04
+
+/**
+ * iSCSI SCSI response basic header segment
+ *
+ */
+struct iscsi_bhs_scsi_response {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Response code */
+ uint8_t response;
+ /** SCSI status code */
+ uint8_t status;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Reserved */
+ uint8_t reserved_a[8];
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** SNACK tag */
+ uint32_t snack;
+ /** Status sequence number */
+ uint32_t statsn;
+ /** Expected command sequence number */
+ uint32_t expcmdsn;
+ /** Maximum command sequence number */
+ uint32_t maxcmdsn;
+ /** Expected data sequence number */
+ uint32_t expdatasn;
+ /** Reserved */
+ uint8_t reserved_b[8];
+};
+
+/** SCSI response opcode */
+#define ISCSI_OPCODE_SCSI_RESPONSE 0x21
+
+/** SCSI command completed at target */
+#define ISCSI_RESPONSE_COMMAND_COMPLETE 0x00
+
+/** SCSI target failure */
+#define ISCSI_RESPONSE_TARGET_FAILURE 0x01
+
+/** SCSI sense response code offset
+ *
+ * The SCSI response may contain unsolicited sense data in the data
+ * segment. If it does, this is the offset to the sense response code
+ * byte, which is the only byte we care about.
+ */
+#define ISCSI_SENSE_RESPONSE_CODE_OFFSET 2
+
+/**
+ * iSCSI data-in basic header segment
+ *
+ */
+struct iscsi_bhs_data_in {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Reserved */
+ uint8_t reserved_a;
+ /** SCSI status code */
+ uint8_t status;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Logical Unit Number */
+ uint64_t lun;
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Target Transfer Tag */
+ uint32_t ttt;
+ /** Status sequence number */
+ uint32_t statsn;
+ /** Expected command sequence number */
+ uint32_t expcmdsn;
+ /** Maximum command sequence number */
+ uint32_t maxcmdsn;
+ /** Data sequence number */
+ uint32_t datasn;
+ /** Buffer offset */
+ uint32_t offset;
+ /** Residual count */
+ uint32_t residual_count;
+};
+
+/** Data-in opcode */
+#define ISCSI_OPCODE_DATA_IN 0x25
+
+/** Data requires acknowledgement */
+#define ISCSI_DATA_FLAG_ACKNOWLEDGE 0x40
+
+/** Data overflow occurred */
+#define ISCSI_DATA_FLAG_OVERFLOW 0x04
+
+/** Data underflow occurred */
+#define ISCSI_DATA_FLAG_UNDERFLOW 0x02
+
+/** SCSI status code and overflow/underflow flags are valid */
+#define ISCSI_DATA_FLAG_STATUS 0x01
+
+/**
+ * iSCSI data-out basic header segment
+ *
+ */
+struct iscsi_bhs_data_out {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Reserved */
+ uint16_t reserved_a;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Logical Unit Number */
+ uint64_t lun;
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Target Transfer Tag */
+ uint32_t ttt;
+ /** Reserved */
+ uint32_t reserved_b;
+ /** Expected status sequence number */
+ uint32_t expstatsn;
+ /** Reserved */
+ uint32_t reserved_c;
+ /** Data sequence number */
+ uint32_t datasn;
+ /** Buffer offset */
+ uint32_t offset;
+ /** Reserved */
+ uint32_t reserved_d;
+};
+
+/** Data-out opcode */
+#define ISCSI_OPCODE_DATA_OUT 0x05
+
+/**
+ * iSCSI request to transfer basic header segment
+ *
+ */
+struct iscsi_bhs_r2t {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Reserved */
+ uint16_t reserved_a;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Logical Unit Number */
+ uint64_t lun;
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Target Transfer Tag */
+ uint32_t ttt;
+ /** Status sequence number */
+ uint32_t statsn;
+ /** Expected command sequence number */
+ uint32_t expcmdsn;
+ /** Maximum command sequence number */
+ uint32_t maxcmdsn;
+ /** R2T sequence number */
+ uint32_t r2tsn;
+ /** Buffer offset */
+ uint32_t offset;
+ /** Desired data transfer length */
+ uint32_t len;
+};
+
+/** R2T opcode */
+#define ISCSI_OPCODE_R2T 0x31
+
+/**
+ * An iSCSI basic header segment
+ */
+union iscsi_bhs {
+ struct iscsi_bhs_common common;
+ struct iscsi_bhs_common_response common_response;
+ struct iscsi_bhs_login_request login_request;
+ struct iscsi_bhs_login_response login_response;
+ struct iscsi_bhs_scsi_command scsi_command;
+ struct iscsi_bhs_scsi_response scsi_response;
+ struct iscsi_bhs_data_in data_in;
+ struct iscsi_bhs_data_out data_out;
+ struct iscsi_bhs_r2t r2t;
+ unsigned char bytes[ sizeof ( struct iscsi_bhs_common ) ];
+};
+
+/** State of an iSCSI TX engine */
+enum iscsi_tx_state {
+ /** Nothing to send */
+ ISCSI_TX_IDLE = 0,
+ /** Sending the basic header segment */
+ ISCSI_TX_BHS,
+ /** Sending the additional header segment */
+ ISCSI_TX_AHS,
+ /** Sending the data segment */
+ ISCSI_TX_DATA,
+ /** Sending the data segment padding */
+ ISCSI_TX_DATA_PADDING,
+};
+
+/** State of an iSCSI RX engine */
+enum iscsi_rx_state {
+ /** Receiving the basic header segment */
+ ISCSI_RX_BHS = 0,
+ /** Receiving the additional header segment */
+ ISCSI_RX_AHS,
+ /** Receiving the data segment */
+ ISCSI_RX_DATA,
+ /** Receiving the data segment padding */
+ ISCSI_RX_DATA_PADDING,
+};
+
+/** An iSCSI session */
+struct iscsi_session {
+ /** Reference counter */
+ struct refcnt refcnt;
+
+ /** Transport-layer socket */
+ struct xfer_interface socket;
+
+ /** Target address */
+ char *target_address;
+ /** Target port */
+ unsigned int target_port;
+ /** Target IQN */
+ char *target_iqn;
+ /** Logical Unit Number (LUN) */
+ uint64_t lun;
+ /** Target socket address (recorded only for iBFT) */
+ struct sockaddr target_sockaddr;
+
+ /** Session status
+ *
+ * This is the bitwise-OR of zero or more ISCSI_STATUS_XXX
+ * constants.
+ */
+ int status;
+ /** Retry count
+ *
+ * Number of times that the connection has been retried.
+ * Reset upon a successful connection.
+ */
+ int retry_count;
+
+ /** Username (if any) */
+ char *username;
+ /** Password (if any) */
+ char *password;
+ /** CHAP challenge/response */
+ struct chap_challenge chap;
+
+ /** Target session identifying handle
+ *
+ * This is assigned by the target when we first log in, and
+ * must be reused on subsequent login attempts.
+ */
+ uint16_t tsih;
+ /** Initiator task tag
+ *
+ * This is the tag of the current command. It is incremented
+ * whenever a new command is started.
+ */
+ uint32_t itt;
+ /** Target transfer tag
+ *
+ * This is the tag attached to a sequence of data-out PDUs in
+ * response to an R2T.
+ */
+ uint32_t ttt;
+ /**
+ * Transfer offset
+ *
+ * This is the offset for an in-progress sequence of data-out
+ * PDUs in response to an R2T.
+ */
+ uint32_t transfer_offset;
+ /**
+ * Transfer length
+ *
+ * This is the length for an in-progress sequence of data-out
+ * PDUs in response to an R2T.
+ */
+ uint32_t transfer_len;
+ /** Command sequence number
+ *
+ * This is the sequence number of the current command, used to
+ * fill out the CmdSN field in iSCSI request PDUs. It is
+ * updated with the value of the ExpCmdSN field whenever we
+ * receive an iSCSI response PDU containing such a field.
+ */
+ uint32_t cmdsn;
+ /** Status sequence number
+ *
+ * This is the most recent status sequence number present in
+ * the StatSN field of an iSCSI response PDU containing such a
+ * field. Whenever we send an iSCSI request PDU, we fill out
+ * the ExpStatSN field with this value plus one.
+ */
+ uint32_t statsn;
+
+ /** Basic header segment for current TX PDU */
+ union iscsi_bhs tx_bhs;
+ /** State of the TX engine */
+ enum iscsi_tx_state tx_state;
+ /** TX process */
+ struct process process;
+
+ /** Basic header segment for current RX PDU */
+ union iscsi_bhs rx_bhs;
+ /** State of the RX engine */
+ enum iscsi_rx_state rx_state;
+ /** Byte offset within the current RX state */
+ size_t rx_offset;
+ /** Length of the current RX state */
+ size_t rx_len;
+ /** Buffer for received data (not always used) */
+ void *rx_buffer;
+
+ /** Current SCSI command
+ *
+ * Set to NULL when command is complete.
+ */
+ struct scsi_command *command;
+ /** SCSI command return code
+ *
+ * Set to -EINPROGRESS while command is processing.
+ */
+ int rc;
+ /** Instant return code
+ *
+ * Set to a non-zero value if all requests should return
+ * immediately. This can be used to e.g. avoid retrying
+ * logins that are doomed to fail authentication.
+ */
+ int instant_rc;
+};
+
+/** iSCSI session is currently in the security negotiation phase */
+#define ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE \
+ ( ISCSI_LOGIN_CSG_SECURITY_NEGOTIATION | \
+ ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION )
+
+/** iSCSI session is currently in the operational parameter
+ * negotiation phase
+ */
+#define ISCSI_STATUS_OPERATIONAL_NEGOTIATION_PHASE \
+ ( ISCSI_LOGIN_CSG_OPERATIONAL_NEGOTIATION | \
+ ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE )
+
+/** iSCSI session is currently in the full feature phase */
+#define ISCSI_STATUS_FULL_FEATURE_PHASE ISCSI_LOGIN_CSG_FULL_FEATURE_PHASE
+
+/** Mask for all iSCSI session phases */
+#define ISCSI_STATUS_PHASE_MASK ( ISCSI_LOGIN_CSG_MASK | ISCSI_LOGIN_NSG_MASK )
+
+/** iSCSI session needs to send the initial security negotiation strings */
+#define ISCSI_STATUS_STRINGS_SECURITY 0x0100
+
+/** iSCSI session needs to send the CHAP_A string */
+#define ISCSI_STATUS_STRINGS_CHAP_ALGORITHM 0x0200
+
+/** iSCSI session needs to send the CHAP response */
+#define ISCSI_STATUS_STRINGS_CHAP_RESPONSE 0x0400
+
+/** iSCSI session needs to send the operational negotiation strings */
+#define ISCSI_STATUS_STRINGS_OPERATIONAL 0x0800
+
+/** Mask for all iSCSI "needs to send" flags */
+#define ISCSI_STATUS_STRINGS_MASK 0xff00
+
+/** Maximum number of retries at connecting */
+#define ISCSI_MAX_RETRIES 2
+
+extern int iscsi_attach ( struct scsi_device *scsi, const char *root_path );
+extern void iscsi_detach ( struct scsi_device *scsi );
+extern const char * iscsi_initiator_iqn ( void );
+
+#endif /* _GPXE_ISCSI_H */
diff --git a/gpxe/src/include/gpxe/job.h b/gpxe/src/include/gpxe/job.h
new file mode 100644
index 00000000..8e11aa33
--- /dev/null
+++ b/gpxe/src/include/gpxe/job.h
@@ -0,0 +1,165 @@
+#ifndef _GPXE_JOB_H
+#define _GPXE_JOB_H
+
+/** @file
+ *
+ * Job control interfaces
+ *
+ */
+
+#include <stddef.h>
+#include <gpxe/interface.h>
+
+/** Job progress */
+struct job_progress {
+ /** Amount of operation completed so far
+ *
+ * The units for this quantity are arbitrary. @c completed
+ * divded by @total should give something which approximately
+ * represents the progress through the operation. For a
+ * download operation, using byte counts would make sense.
+ */
+ unsigned long completed;
+ /** Total operation size
+ *
+ * See @c completed. A zero value means "total size unknown"
+ * and is explcitly permitted; users should take this into
+ * account before calculating @c completed/total.
+ */
+ unsigned long total;
+};
+
+struct job_interface;
+
+/** Job control interface operations */
+struct job_interface_operations {
+ /** Job completed
+ *
+ * @v job Job control interface
+ * @v rc Overall job status code
+ */
+ void ( * done ) ( struct job_interface *job, int rc );
+ /** Abort job
+ *
+ * @v job Job control interface
+ */
+ void ( * kill ) ( struct job_interface *job );
+ /** Get job progress
+ *
+ * @v job Job control interface
+ * @v progress Progress data to fill in
+ */
+ void ( * progress ) ( struct job_interface *job,
+ struct job_progress *progress );
+};
+
+/** A job control interface */
+struct job_interface {
+ /** Generic object communication interface */
+ struct interface intf;
+ /** Operations for received messages */
+ struct job_interface_operations *op;
+};
+
+extern struct job_interface null_job;
+extern struct job_interface_operations null_job_ops;
+
+extern void job_done ( struct job_interface *job, int rc );
+extern void job_kill ( struct job_interface *job );
+
+extern void ignore_job_done ( struct job_interface *job, int rc );
+extern void ignore_job_kill ( struct job_interface *job );
+extern void ignore_job_progress ( struct job_interface *job,
+ struct job_progress *progress );
+
+/**
+ * Initialise a job control interface
+ *
+ * @v job Job control interface
+ * @v op Job control interface operations
+ * @v refcnt Containing object reference counter, or NULL
+ */
+static inline void job_init ( struct job_interface *job,
+ struct job_interface_operations *op,
+ struct refcnt *refcnt ) {
+ job->intf.dest = &null_job.intf;
+ job->intf.refcnt = refcnt;
+ job->op = op;
+}
+
+/**
+ * Get job control interface from generic object communication interface
+ *
+ * @v intf Generic object communication interface
+ * @ret job Job control interface
+ */
+static inline __attribute__ (( always_inline )) struct job_interface *
+intf_to_job ( struct interface *intf ) {
+ return container_of ( intf, struct job_interface, intf );
+}
+
+/**
+ * Get reference to destination job control interface
+ *
+ * @v job Job control interface
+ * @ret dest Destination interface
+ */
+static inline __attribute__ (( always_inline )) struct job_interface *
+job_get_dest ( struct job_interface *job ) {
+ return intf_to_job ( intf_get ( job->intf.dest ) );
+}
+
+/**
+ * Drop reference to job control interface
+ *
+ * @v job Job control interface
+ */
+static inline __attribute__ (( always_inline )) void
+job_put ( struct job_interface *job ) {
+ intf_put ( &job->intf );
+}
+
+/**
+ * Plug a job control interface into a new destination interface
+ *
+ * @v job Job control interface
+ * @v dest New destination interface
+ */
+static inline void job_plug ( struct job_interface *job,
+ struct job_interface *dest ) {
+ plug ( &job->intf, &dest->intf );
+}
+
+/**
+ * Plug two job control interfaces together
+ *
+ * @v a Job control interface A
+ * @v b Job control interface B
+ */
+static inline void job_plug_plug ( struct job_interface *a,
+ struct job_interface *b ) {
+ plug_plug ( &a->intf, &b->intf );
+}
+
+/**
+ * Unplug a job control interface
+ *
+ * @v job Job control interface
+ */
+static inline void job_unplug ( struct job_interface *job ) {
+ plug ( &job->intf, &null_job.intf );
+}
+
+/**
+ * Stop using a job control interface
+ *
+ * @v job Job control interface
+ *
+ * After calling this method, no further messages will be received via
+ * the interface.
+ */
+static inline void job_nullify ( struct job_interface *job ) {
+ job->op = &null_job_ops;
+};
+
+#endif /* _GPXE_JOB_H */
diff --git a/gpxe/src/include/gpxe/keys.h b/gpxe/src/include/gpxe/keys.h
new file mode 100644
index 00000000..7a0b5101
--- /dev/null
+++ b/gpxe/src/include/gpxe/keys.h
@@ -0,0 +1,82 @@
+#ifndef _GPXE_KEYS_H
+#define _GPXE_KEYS_H
+
+/** @file
+ *
+ * Key definitions
+ *
+ */
+
+/*
+ * Symbolic names for some standard ASCII characters
+ *
+ */
+
+#define NUL 0x00
+#define CTRL_A 0x01
+#define CTRL_B 0x02
+#define CTRL_C 0x03
+#define CTRL_D 0x04
+#define CTRL_E 0x05
+#define CTRL_F 0x06
+#define CTRL_G 0x07
+#define CTRL_H 0x08
+#define CTRL_I 0x09
+#define CTRL_J 0x0a
+#define CTRL_K 0x0b
+#define CTRL_L 0x0c
+#define CTRL_M 0x0d
+#define CTRL_N 0x0e
+#define CTRL_O 0x0f
+#define CTRL_P 0x10
+#define CTRL_Q 0x11
+#define CTRL_R 0x12
+#define CTRL_S 0x13
+#define CTRL_T 0x14
+#define CTRL_U 0x15
+#define CTRL_V 0x16
+#define CTRL_W 0x17
+#define CTRL_X 0x18
+#define CTRL_Y 0x19
+#define CTRL_Z 0x1a
+
+#define BACKSPACE CTRL_H
+#define TAB CTRL_I
+#define LF CTRL_J
+#define CR CTRL_M
+#define ESC 0x1b
+
+/*
+ * Special keys outside the normal ASCII 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. The KEY_XXX constant is simply
+ * 0x100 plus the first byte following CSI in the ANSI escape
+ * sequence. For example, KEY_LEFT is 0x144, since a left cursor key
+ * is transmitted as the ANSI sequence "^[[D".
+ */
+
+#define KEY_ANSI( character ) ( 0x100 + (character) )
+
+#define KEY_MIN 0x101
+#define KEY_UP KEY_ANSI ( 'A' ) /**< Up arrow */
+#define KEY_DOWN KEY_ANSI ( 'B' ) /**< Down arrow */
+#define KEY_RIGHT KEY_ANSI ( 'C' ) /**< Right arrow */
+#define KEY_LEFT KEY_ANSI ( 'D' ) /**< Left arrow */
+#define KEY_END KEY_ANSI ( 'F' ) /**< End */
+#define KEY_HOME KEY_ANSI ( 'H' ) /**< Home */
+#define KEY_IC KEY_ANSI ( '2' ) /**< Insert */
+#define KEY_DC KEY_ANSI ( '3' ) /**< Delete */
+#define KEY_PPAGE KEY_ANSI ( '5' ) /**< Page up */
+#define KEY_NPAGE KEY_ANSI ( '6' ) /**< Page down */
+#define KEY_MAX 0x1ff
+
+/* Not in the [KEY_MIN,KEY_MAX] range; terminals seem to send these as
+ * normal ASCII values.
+ */
+#define KEY_BACKSPACE BACKSPACE
+#define KEY_ENTER LF
+
+#endif /* _GPXE_KEYS_H */
diff --git a/gpxe/src/include/gpxe/linebuf.h b/gpxe/src/include/gpxe/linebuf.h
new file mode 100644
index 00000000..676731a9
--- /dev/null
+++ b/gpxe/src/include/gpxe/linebuf.h
@@ -0,0 +1,28 @@
+#ifndef _GPXE_LINEBUF_H
+#define _GPXE_LINEBUF_H
+
+/** @file
+ *
+ * Line buffering
+ *
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+
+/** A line buffer */
+struct line_buffer {
+ /** Current string in the buffer */
+ char *data;
+ /** Length of current string, excluding the terminating NUL */
+ size_t len;
+ /** String is ready to read */
+ int ready;
+};
+
+extern char * buffered_line ( struct line_buffer *linebuf );
+extern ssize_t line_buffer ( struct line_buffer *linebuf,
+ const char *data, size_t len );
+extern void empty_line_buffer ( struct line_buffer *linebuf );
+
+#endif /* _GPXE_LINEBUF_H */
diff --git a/gpxe/src/include/gpxe/linux_compat.h b/gpxe/src/include/gpxe/linux_compat.h
new file mode 100644
index 00000000..2c3cbbde
--- /dev/null
+++ b/gpxe/src/include/gpxe/linux_compat.h
@@ -0,0 +1,25 @@
+#ifndef _GPXE_LINUX_COMPAT_H
+#define _GPXE_LINUX_COMPAT_H
+
+/** @file
+ *
+ * Linux code compatibility
+ *
+ * This file exists to ease the building of Linux source code within
+ * gPXE. This is intended to facilitate quick testing; it is not
+ * intended to be a substitute for proper porting.
+ */
+
+#include <stdint.h>
+#include <errno.h>
+#include <stdio.h>
+#include <byteswap.h>
+#include <gpxe/bitops.h>
+
+#define __init
+#define __exit
+#define __initdata
+#define __exitdata
+#define printk printf
+
+#endif /* _GPXE_LINUX_COMPAT_H */
diff --git a/gpxe/src/include/gpxe/list.h b/gpxe/src/include/gpxe/list.h
new file mode 100644
index 00000000..602382be
--- /dev/null
+++ b/gpxe/src/include/gpxe/list.h
@@ -0,0 +1,178 @@
+#ifndef _GPXE_LIST_H
+#define _GPXE_LIST_H
+
+/** @file
+ *
+ * Linked lists
+ *
+ * This linked list handling code is based on the Linux kernel's
+ * list.h.
+ */
+
+#include <stddef.h>
+#include <assert.h>
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+ struct list_head *next;
+ struct list_head *prev;
+};
+
+#define LIST_HEAD_INIT( name ) { &(name), &(name) }
+
+#define LIST_HEAD( name ) \
+ struct list_head name = LIST_HEAD_INIT ( name )
+
+#define INIT_LIST_HEAD( ptr ) do { \
+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while ( 0 )
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add ( struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next ) {
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/**
+ * Add a new entry to the head of a list
+ *
+ * @v new New entry to be added
+ * @v head List head to add it after
+ *
+ * Insert a new entry after the specified head. This is good for
+ * implementing stacks.
+ */
+static inline void list_add ( struct list_head *new, struct list_head *head ) {
+ __list_add ( new, head, head->next );
+}
+#define list_add( new, head ) do { \
+ assert ( (head)->next->prev == (head) ); \
+ assert ( (head)->prev->next == (head) ); \
+ list_add ( (new), (head) ); \
+ } while ( 0 )
+
+/**
+ * Add a new entry to the tail of a list
+ *
+ * @v new New entry to be added
+ * @v head List head to add it before
+ *
+ * Insert a new entry before the specified head. This is useful for
+ * implementing queues.
+ */
+static inline void list_add_tail ( struct list_head *new,
+ struct list_head *head ) {
+ __list_add ( new, head->prev, head );
+}
+#define list_add_tail( new, head ) do { \
+ assert ( (head)->next->prev == (head) ); \
+ assert ( (head)->prev->next == (head) ); \
+ list_add_tail ( (new), (head) ); \
+ } while ( 0 )
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del ( struct list_head * prev,
+ struct list_head * next ) {
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * Delete an entry from a list
+ *
+ * @v entry Element to delete from the list
+ *
+ * Note that list_empty() on entry does not return true after this;
+ * the entry is in an undefined state.
+ */
+static inline void list_del ( struct list_head *entry ) {
+ __list_del ( entry->prev, entry->next );
+}
+#define list_del( entry ) do { \
+ assert ( (entry)->prev != NULL ); \
+ assert ( (entry)->next != NULL ); \
+ assert ( (entry)->next->prev == (entry) ); \
+ assert ( (entry)->prev->next == (entry) ); \
+ list_del ( (entry) ); \
+ } while ( 0 )
+
+/**
+ * Test whether a list is empty
+ *
+ * @v head List to test.
+ */
+static inline int list_empty ( const struct list_head *head ) {
+ return head->next == head;
+}
+
+/**
+ * Get the containing struct for this entry
+ *
+ * @v ptr The struct list_head pointer
+ * @v type The type of the struct this is embedded in
+ * @v member The name of the list_struct within the struct
+ */
+#define list_entry( ptr, type, member ) \
+ container_of ( ptr, type, member )
+
+/**
+ * Iterate over a list
+ *
+ * @v pos The &struct list_head to use as a loop counter
+ * @v head The head for your list
+ */
+#define list_for_each( pos, head ) \
+ for ( pos = (head)->next; pos != (head); pos = pos->next )
+
+/**
+ * Iterate over entries in a list
+ *
+ * @v pos The type * to use as a loop counter
+ * @v head The head for your list
+ * @v member The name of the list_struct within the struct
+ */
+#define list_for_each_entry( pos, head, member ) \
+ for ( pos = list_entry ( (head)->next, typeof ( *pos ), member ); \
+ &pos->member != (head); \
+ pos = list_entry ( pos->member.next, typeof ( *pos ), member ) )
+
+/**
+ * Iterate over entries in a list, safe against deletion of entries
+ *
+ * @v pos The type * to use as a loop counter
+ * @v tmp Another type * to use for temporary storage
+ * @v head The head for your list
+ * @v member The name of the list_struct within the struct
+ */
+#define list_for_each_entry_safe( pos, tmp, head, member ) \
+ for ( pos = list_entry ( (head)->next, typeof ( *pos ), member ), \
+ tmp = list_entry ( pos->member.next, typeof ( *tmp ), member ); \
+ &pos->member != (head); \
+ pos = tmp, \
+ tmp = list_entry ( tmp->member.next, typeof ( *tmp ), member ) )
+
+#endif /* _GPXE_LIST_H */
diff --git a/gpxe/src/include/gpxe/malloc.h b/gpxe/src/include/gpxe/malloc.h
new file mode 100644
index 00000000..cce5d1d3
--- /dev/null
+++ b/gpxe/src/include/gpxe/malloc.h
@@ -0,0 +1,57 @@
+#ifndef _GPXE_MALLOC_H
+#define _GPXE_MALLOC_H
+
+#include <stdint.h>
+
+/** @file
+ *
+ * Dynamic memory allocation
+ *
+ */
+
+/*
+ * Prototypes for the standard functions (malloc() et al) are in
+ * stdlib.h. Include <gpxe/malloc.h> only if you need the
+ * non-standard functions, such as malloc_dma().
+ *
+ */
+#include <stdlib.h>
+
+extern size_t freemem;
+
+extern void * __malloc alloc_memblock ( size_t size, size_t align );
+extern void free_memblock ( void *ptr, size_t size );
+extern void mpopulate ( void *start, size_t len );
+extern void mdumpfree ( void );
+
+/**
+ * Allocate memory for DMA
+ *
+ * @v size Requested size
+ * @v align Physical alignment
+ * @ret ptr Memory, or NULL
+ *
+ * Allocates physically-aligned memory for DMA.
+ *
+ * @c align must be a power of two. @c size may not be zero.
+ */
+static inline void * __malloc malloc_dma ( size_t size, size_t phys_align ) {
+ return alloc_memblock ( size, phys_align );
+}
+
+/**
+ * Free memory allocated with malloc_dma()
+ *
+ * @v ptr Memory allocated by malloc_dma(), or NULL
+ * @v size Size of memory, as passed to malloc_dma()
+ *
+ * Memory allocated with malloc_dma() can only be freed with
+ * free_dma(); it cannot be freed with the standard free().
+ *
+ * If @c ptr is NULL, no action is taken.
+ */
+static inline void free_dma ( void *ptr, size_t size ) {
+ free_memblock ( ptr, size );
+}
+
+#endif /* _GPXE_MALLOC_H */
diff --git a/gpxe/src/include/gpxe/mca.h b/gpxe/src/include/gpxe/mca.h
new file mode 100644
index 00000000..21f9e74d
--- /dev/null
+++ b/gpxe/src/include/gpxe/mca.h
@@ -0,0 +1,103 @@
+/*
+ * MCA bus driver code
+ *
+ * Abstracted from 3c509.c.
+ *
+ */
+
+#ifndef MCA_H
+#define MCA_H
+
+#include <gpxe/isa_ids.h>
+#include <gpxe/device.h>
+#include <gpxe/tables.h>
+
+/*
+ * MCA constants
+ *
+ */
+#define MCA_MOTHERBOARD_SETUP_REG 0x94
+#define MCA_ADAPTER_SETUP_REG 0x96
+#define MCA_MAX_SLOT_NR 0x07 /* Must be 2^n - 1 */
+#define MCA_POS_REG(n) (0x100+(n))
+
+/* Is there a standard that would define this? */
+#define GENERIC_MCA_VENDOR ISA_VENDOR ( 'M', 'C', 'A' )
+
+/** An MCA device ID list entry */
+struct mca_device_id {
+ /** Name */
+ const char *name;
+ /** Device ID */
+ uint16_t id;
+};
+
+/** An MCA device */
+struct mca_device {
+ /** Generic device */
+ struct device dev;
+ /** Slot number */
+ unsigned int slot;
+ /** POS register values */
+ unsigned char pos[8];
+ /** Driver for this device */
+ struct mca_driver *driver;
+ /** Driver-private data
+ *
+ * Use mca_set_drvdata() and mca_get_drvdata() to access
+ * this field.
+ */
+ void *priv;
+ /** Driver name */
+ const char *driver_name;
+};
+
+#define MCA_ID(mca) ( ( (mca)->pos[1] << 8 ) + (mca)->pos[0] )
+
+/** An MCA driver */
+struct mca_driver {
+ /** MCA ID table */
+ struct mca_device_id *ids;
+ /** Number of entries in MCA ID table */
+ unsigned int id_count;
+ /**
+ * Probe device
+ *
+ * @v mca MCA device
+ * @v id Matching entry in ID table
+ * @ret rc Return status code
+ */
+ int ( * probe ) ( struct mca_device *mca,
+ const struct mca_device_id *id );
+ /**
+ * Remove device
+ *
+ * @v mca MCA device
+ */
+ void ( * remove ) ( struct mca_device *mca );
+};
+
+/** Declare an MCA driver */
+#define __mca_driver __table ( struct mca_driver, mca_drivers, 01 )
+
+/**
+ * Set MCA driver-private data
+ *
+ * @v mca MCA device
+ * @v priv Private data
+ */
+static inline void mca_set_drvdata ( struct mca_device *mca, void *priv ) {
+ mca->priv = priv;
+}
+
+/**
+ * Get MCA driver-private data
+ *
+ * @v mca MCA device
+ * @ret priv Private data
+ */
+static inline void * mca_get_drvdata ( struct mca_device *mca ) {
+ return mca->priv;
+}
+
+#endif
diff --git a/gpxe/src/include/gpxe/md5.h b/gpxe/src/include/gpxe/md5.h
new file mode 100644
index 00000000..304a0e64
--- /dev/null
+++ b/gpxe/src/include/gpxe/md5.h
@@ -0,0 +1,22 @@
+#ifndef _GPXE_MD5_H
+#define _GPXE_MD5_H
+
+struct crypto_algorithm;
+
+#include <stdint.h>
+
+#define MD5_DIGEST_SIZE 16
+#define MD5_BLOCK_WORDS 16
+#define MD5_HASH_WORDS 4
+
+struct md5_ctx {
+ u32 hash[MD5_HASH_WORDS];
+ u32 block[MD5_BLOCK_WORDS];
+ u64 byte_count;
+};
+
+#define MD5_CTX_SIZE sizeof ( struct md5_ctx )
+
+extern struct crypto_algorithm md5_algorithm;
+
+#endif /* _GPXE_MD5_H */
diff --git a/gpxe/src/include/gpxe/memmap.h b/gpxe/src/include/gpxe/memmap.h
new file mode 100644
index 00000000..836a1b92
--- /dev/null
+++ b/gpxe/src/include/gpxe/memmap.h
@@ -0,0 +1,34 @@
+#ifndef _GPXE_MEMMAP_H
+#define _GPXE_MEMMAP_H
+
+#include <stdint.h>
+
+/**
+ * @file
+ *
+ * Memory mapping
+ *
+ */
+
+/** A usable memory region */
+struct memory_region {
+ /** Physical start address */
+ uint64_t start;
+ /** Physical end address */
+ uint64_t end;
+};
+
+/** Maximum number of memory regions we expect to encounter */
+#define MAX_MEMORY_REGIONS 8
+
+/** A memory map */
+struct memory_map {
+ /** Memory regions */
+ struct memory_region regions[MAX_MEMORY_REGIONS];
+ /** Number of used regions */
+ unsigned int count;
+};
+
+extern void get_memmap ( struct memory_map *memmap );
+
+#endif /* _GPXE_MEMMAP_H */
diff --git a/gpxe/src/include/gpxe/monojob.h b/gpxe/src/include/gpxe/monojob.h
new file mode 100644
index 00000000..aaa38d03
--- /dev/null
+++ b/gpxe/src/include/gpxe/monojob.h
@@ -0,0 +1,15 @@
+#ifndef _GPXE_MONOJOB_H
+#define _GPXE_MONOJOB_H
+
+/** @file
+ *
+ * Single foreground job
+ *
+ */
+
+struct job_interface;
+
+extern struct job_interface monojob;
+extern int monojob_wait ( const char *string );
+
+#endif /* _GPXE_MONOJOB_H */
diff --git a/gpxe/src/include/gpxe/ndp.h b/gpxe/src/include/gpxe/ndp.h
new file mode 100644
index 00000000..db32b0c8
--- /dev/null
+++ b/gpxe/src/include/gpxe/ndp.h
@@ -0,0 +1,21 @@
+#include <stdint.h>
+#include <byteswap.h>
+#include <string.h>
+#include <gpxe/icmp6.h>
+#include <gpxe/ip6.h>
+#include <gpxe/in.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/tcpip.h>
+
+#define NDP_STATE_INVALID 0
+#define NDP_STATE_INCOMPLETE 1
+#define NDP_STATE_REACHABLE 2
+#define NDP_STATE_DELAY 3
+#define NDP_STATE_PROBE 4
+#define NDP_STATE_STALE 5
+
+int ndp_resolve ( struct net_device *netdev, struct in6_addr *src,
+ struct in6_addr *dest, void *dest_ll_addr );
+int ndp_process_advert ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest );
diff --git a/gpxe/src/include/gpxe/netdevice.h b/gpxe/src/include/gpxe/netdevice.h
new file mode 100644
index 00000000..d8cb84d0
--- /dev/null
+++ b/gpxe/src/include/gpxe/netdevice.h
@@ -0,0 +1,404 @@
+#ifndef _GPXE_NETDEVICE_H
+#define _GPXE_NETDEVICE_H
+
+/** @file
+ *
+ * Network device management
+ *
+ */
+
+#include <stdint.h>
+#include <gpxe/list.h>
+#include <gpxe/tables.h>
+#include <gpxe/refcnt.h>
+#include <gpxe/settings.h>
+
+struct io_buffer;
+struct net_device;
+struct net_protocol;
+struct ll_protocol;
+struct device;
+
+/** Maximum length of a link-layer address */
+#define MAX_LL_ADDR_LEN 20
+
+/** Maximum length of a link-layer header */
+#define MAX_LL_HEADER_LEN 32
+
+/** Maximum length of a network-layer address */
+#define MAX_NET_ADDR_LEN 4
+
+/**
+ * A network-layer protocol
+ *
+ */
+struct net_protocol {
+ /** Protocol name */
+ const char *name;
+ /**
+ * Process received packet
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v ll_source Link-layer source address
+ *
+ * This method takes ownership of the I/O buffer.
+ */
+ int ( * rx ) ( struct io_buffer *iobuf, struct net_device *netdev,
+ const void *ll_source );
+ /**
+ * Transcribe network-layer address
+ *
+ * @v net_addr Network-layer address
+ * @ret string Human-readable transcription of address
+ *
+ * This method should convert the network-layer address into a
+ * human-readable format (e.g. dotted quad notation for IPv4).
+ *
+ * The buffer used to hold the transcription is statically
+ * allocated.
+ */
+ const char * ( *ntoa ) ( const void * net_addr );
+ /** Network-layer protocol
+ *
+ * This is an ETH_P_XXX constant, in network-byte order
+ */
+ uint16_t net_proto;
+ /** Network-layer address length */
+ uint8_t net_addr_len;
+};
+
+/**
+ * A link-layer protocol
+ *
+ */
+struct ll_protocol {
+ /** Protocol name */
+ const char *name;
+ /**
+ * Transmit network-layer packet via network device
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v net_protocol Network-layer protocol
+ * @v ll_dest Link-layer destination address
+ * @ret rc Return status code
+ *
+ * This method should prepend in the link-layer header
+ * (e.g. the Ethernet DIX header) and transmit the packet.
+ * This method takes ownership of the I/O buffer.
+ */
+ int ( * tx ) ( struct io_buffer *iobuf, struct net_device *netdev,
+ struct net_protocol *net_protocol,
+ const void *ll_dest );
+ /**
+ * Handle received packet
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ *
+ * This method should strip off the link-layer header
+ * (e.g. the Ethernet DIX header) and pass the packet to
+ * net_rx(). This method takes ownership of the packet
+ * buffer.
+ */
+ int ( * rx ) ( struct io_buffer *iobuf, struct net_device *netdev );
+ /**
+ * Transcribe link-layer address
+ *
+ * @v ll_addr Link-layer address
+ * @ret string Human-readable transcription of address
+ *
+ * This method should convert the link-layer address into a
+ * human-readable format.
+ *
+ * The buffer used to hold the transcription is statically
+ * allocated.
+ */
+ const char * ( * ntoa ) ( const void * ll_addr );
+ /** Link-layer protocol
+ *
+ * This is an ARPHRD_XXX constant, in network byte order.
+ */
+ uint16_t ll_proto;
+ /** Link-layer address length */
+ uint8_t ll_addr_len;
+ /** Link-layer header length */
+ uint8_t ll_header_len;
+ /** Link-layer broadcast address */
+ const uint8_t *ll_broadcast;
+};
+
+/** Network device operations */
+struct net_device_operations {
+ /** Open network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ *
+ * This method should allocate RX I/O buffers and enable
+ * the hardware to start transmitting and receiving packets.
+ */
+ int ( * open ) ( struct net_device *netdev );
+ /** Close network device
+ *
+ * @v netdev Network device
+ *
+ * This method should stop the flow of packets, and free up
+ * any packets that are currently in the device's TX queue.
+ */
+ void ( * close ) ( struct net_device *netdev );
+ /** Transmit packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ *
+ * This method should cause the hardware to initiate
+ * transmission of the I/O buffer.
+ *
+ * If this method returns success, the I/O buffer remains
+ * owned by the net device's TX queue, and the net device must
+ * eventually call netdev_tx_complete() to free the buffer.
+ * If this method returns failure, the I/O buffer is
+ * immediately released; the failure is interpreted as
+ * "failure to enqueue buffer".
+ *
+ * This method is guaranteed to be called only when the device
+ * is open.
+ */
+ int ( * transmit ) ( struct net_device *netdev,
+ struct io_buffer *iobuf );
+ /** Poll for completed and received packets
+ *
+ * @v netdev Network device
+ *
+ * This method should cause the hardware to check for
+ * completed transmissions and received packets. Any received
+ * packets should be delivered via netdev_rx().
+ *
+ * This method is guaranteed to be called only when the device
+ * is open.
+ */
+ void ( * poll ) ( struct net_device *netdev );
+ /** Enable or disable interrupts
+ *
+ * @v netdev Network device
+ * @v enable Interrupts should be enabled
+ */
+ void ( * irq ) ( struct net_device *netdev, int enable );
+};
+
+/** Network device statistics */
+struct net_device_stats {
+ /** Count of successfully completed transmissions */
+ unsigned int tx_ok;
+ /** Count of transmission errors */
+ unsigned int tx_err;
+ /** Count of successfully received packets */
+ unsigned int rx_ok;
+ /** Count of reception errors */
+ unsigned int rx_err;
+};
+
+/**
+ * A network device
+ *
+ * This structure represents a piece of networking hardware. It has
+ * properties such as a link-layer address and methods for
+ * transmitting and receiving raw packets.
+ *
+ * Note that this structure must represent a generic network device,
+ * not just an Ethernet device.
+ */
+struct net_device {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** List of network devices */
+ struct list_head list;
+ /** Name of this network device */
+ char name[8];
+ /** Underlying hardware device */
+ struct device *dev;
+
+ /** Network device operations */
+ struct net_device_operations *op;
+
+ /** Link-layer protocol */
+ struct ll_protocol *ll_protocol;
+ /** Link-layer address
+ *
+ * For Ethernet, this is the MAC address.
+ */
+ uint8_t ll_addr[MAX_LL_ADDR_LEN];
+
+ /** Current device state
+ *
+ * This is the bitwise-OR of zero or more NETDEV_XXX constants.
+ */
+ unsigned int state;
+ /** TX packet queue */
+ struct list_head tx_queue;
+ /** RX packet queue */
+ struct list_head rx_queue;
+ /** Device statistics */
+ struct net_device_stats stats;
+
+ /** Configuration settings applicable to this device */
+ struct simple_settings settings;
+
+ /** Driver private data */
+ void *priv;
+};
+
+/** Network device is open */
+#define NETDEV_OPEN 0x0001
+
+/** Declare a link-layer protocol */
+#define __ll_protocol __table ( struct ll_protocol, ll_protocols, 01 )
+
+/** Declare a network-layer protocol */
+#define __net_protocol __table ( struct net_protocol, net_protocols, 01 )
+
+extern struct list_head net_devices;
+extern struct net_device_operations null_netdev_operations;
+
+/**
+ * Initialise a network device
+ *
+ * @v netdev Network device
+ * @v op Network device operations
+ */
+static inline void netdev_init ( struct net_device *netdev,
+ struct net_device_operations *op ) {
+ netdev->op = op;
+}
+
+/**
+ * Stop using a network device
+ *
+ * @v netdev Network device
+ *
+ * Drivers should call this method immediately before the final call
+ * to netdev_put().
+ */
+static inline void netdev_nullify ( struct net_device *netdev ) {
+ netdev->op = &null_netdev_operations;
+}
+
+/**
+ * Get printable network device hardware address
+ *
+ * @v netdev Network device
+ * @ret name Hardware address
+ */
+static inline const char * netdev_hwaddr ( struct net_device *netdev ) {
+ return netdev->ll_protocol->ntoa ( netdev->ll_addr );
+}
+
+/** Iterate over all network devices */
+#define for_each_netdev( netdev ) \
+ list_for_each_entry ( (netdev), &net_devices, list )
+
+/** There exist some network devices
+ *
+ * @ret existence Existence of network devices
+ */
+static inline int have_netdevs ( void ) {
+ return ( ! list_empty ( &net_devices ) );
+}
+
+/**
+ * Get reference to network device
+ *
+ * @v netdev Network device
+ * @ret netdev Network device
+ */
+static inline __attribute__ (( always_inline )) struct net_device *
+netdev_get ( struct net_device *netdev ) {
+ ref_get ( &netdev->refcnt );
+ return netdev;
+}
+
+/**
+ * Drop reference to network device
+ *
+ * @v netdev Network device
+ */
+static inline __attribute__ (( always_inline )) void
+netdev_put ( struct net_device *netdev ) {
+ ref_put ( &netdev->refcnt );
+}
+
+/**
+ * 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
+ * @ret settings Settings block
+ */
+static inline __attribute__ (( always_inline )) struct settings *
+netdev_settings ( struct net_device *netdev ) {
+ return &netdev->settings.settings;
+}
+
+extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf );
+extern void netdev_tx_complete_err ( struct net_device *netdev,
+ struct io_buffer *iobuf, int rc );
+extern void netdev_tx_complete_next_err ( struct net_device *netdev, int rc );
+extern void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf );
+extern void netdev_rx_err ( struct net_device *netdev,
+ struct io_buffer *iobuf, int rc );
+extern void netdev_poll ( struct net_device *netdev );
+extern struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev );
+extern struct net_device * alloc_netdev ( size_t priv_size );
+extern int register_netdev ( struct net_device *netdev );
+extern int netdev_open ( struct net_device *netdev );
+extern void netdev_close ( struct net_device *netdev );
+extern void unregister_netdev ( struct net_device *netdev );
+extern void netdev_irq ( struct net_device *netdev, int enable );
+extern struct net_device * find_netdev ( const char *name );
+extern struct net_device * find_netdev_by_location ( unsigned int bus_type,
+ unsigned int location );
+extern int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
+ struct net_protocol *net_protocol, const void *ll_dest );
+extern int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
+ uint16_t net_proto, const void *ll_source );
+
+extern struct settings_operations netdev_settings_operations;
+
+/**
+ * Complete network transmission
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ *
+ * The packet must currently be in the network device's TX queue.
+ */
+static inline void netdev_tx_complete ( struct net_device *netdev,
+ struct io_buffer *iobuf ) {
+ netdev_tx_complete_err ( netdev, iobuf, 0 );
+}
+
+/**
+ * Complete network transmission
+ *
+ * @v netdev Network device
+ *
+ * Completes the oldest outstanding packet in the TX queue.
+ */
+static inline void netdev_tx_complete_next ( struct net_device *netdev ) {
+ netdev_tx_complete_next_err ( netdev, 0 );
+}
+
+#endif /* _GPXE_NETDEVICE_H */
diff --git a/gpxe/src/include/gpxe/nvo.h b/gpxe/src/include/gpxe/nvo.h
new file mode 100644
index 00000000..28068f4b
--- /dev/null
+++ b/gpxe/src/include/gpxe/nvo.h
@@ -0,0 +1,53 @@
+#ifndef _GPXE_NVO_H
+#define _GPXE_NVO_H
+
+/** @file
+ *
+ * Non-volatile stored options
+ *
+ */
+
+#include <stdint.h>
+#include <gpxe/dhcpopts.h>
+#include <gpxe/settings.h>
+
+struct nvs_device;
+struct refcnt;
+
+/**
+ * A fragment of a non-volatile storage device used for stored options
+ */
+struct nvo_fragment {
+ /** Starting address of fragment within NVS device */
+ unsigned int address;
+ /** Length of fragment */
+ size_t len;
+};
+
+/**
+ * A block of non-volatile stored options
+ */
+struct nvo_block {
+ /** Settings block */
+ struct settings settings;
+ /** Underlying non-volatile storage device */
+ struct nvs_device *nvs;
+ /** List of option-containing fragments
+ *
+ * The list is terminated by a fragment with a length of zero.
+ */
+ struct nvo_fragment *fragments;
+ /** Total length of option-containing fragments */
+ size_t total_len;
+ /** Option-containing data */
+ void *data;
+ /** DHCP options block */
+ struct dhcp_options dhcpopts;
+};
+
+extern void nvo_init ( struct nvo_block *nvo, struct nvs_device *nvs,
+ struct nvo_fragment *fragments, struct refcnt *refcnt );
+extern int register_nvo ( struct nvo_block *nvo, struct settings *parent );
+extern void unregister_nvo ( struct nvo_block *nvo );
+
+#endif /* _GPXE_NVO_H */
diff --git a/gpxe/src/include/gpxe/nvs.h b/gpxe/src/include/gpxe/nvs.h
new file mode 100644
index 00000000..b026dd46
--- /dev/null
+++ b/gpxe/src/include/gpxe/nvs.h
@@ -0,0 +1,66 @@
+#ifndef _GPXE_NVS_H
+#define _GPXE_NVS_H
+
+/** @file
+ *
+ * Non-volatile storage
+ *
+ */
+
+#include <stdint.h>
+
+/** A non-volatile storage device */
+struct nvs_device {
+ /** Word length
+ *
+ * This is expressed as the base-2 logarithm of the word
+ * length in bytes. A value of 0 therefore translates as
+ * 8-bit words, and a value of 1 translates as 16-bit words.
+ */
+ unsigned int word_len_log2;
+ /** Device size (in words) */
+ unsigned int size;
+ /** Data block size (in words)
+ *
+ * This is the block size used by the device. It must be a
+ * power of two. Data reads and writes must not cross a block
+ * boundary.
+ *
+ * Many devices allow reads to cross a block boundary, and
+ * restrict only writes. For the sake of simplicity, we
+ * assume that the same restriction applies to both reads and
+ * writes.
+ */
+ unsigned int block_size;
+ /** Read data from device
+ *
+ * @v nvs NVS device
+ * @v address Address from which to read
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ *
+ * Reads may not cross a block boundary.
+ */
+ int ( * read ) ( struct nvs_device *nvs, unsigned int address,
+ void *data, size_t len );
+ /** Write data to device
+ *
+ * @v nvs NVS device
+ * @v address Address to which to write
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ *
+ * Writes may not cross a block boundary.
+ */
+ int ( * write ) ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t len );
+};
+
+extern int nvs_read ( struct nvs_device *nvs, unsigned int address,
+ void *data, size_t len );
+extern int nvs_write ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t len );
+
+#endif /* _GPXE_NVS_H */
diff --git a/gpxe/src/include/gpxe/open.h b/gpxe/src/include/gpxe/open.h
new file mode 100644
index 00000000..beab0a1f
--- /dev/null
+++ b/gpxe/src/include/gpxe/open.h
@@ -0,0 +1,95 @@
+#ifndef _GPXE_OPEN_H
+#define _GPXE_OPEN_H
+
+/** @file
+ *
+ * Data transfer interface opening
+ *
+ */
+
+#include <stdarg.h>
+#include <gpxe/tables.h>
+
+struct xfer_interface;
+struct uri;
+struct sockaddr;
+
+/** Location types */
+enum {
+ /** Location is a URI
+ *
+ * Parameter list for open() is:
+ *
+ * struct uri *uri;
+ */
+ LOCATION_URI = 1,
+ /** Location is a URI string
+ *
+ * Parameter list for open() is:
+ *
+ * const char *uri_string;
+ */
+ LOCATION_URI_STRING,
+ /** Location is a socket
+ *
+ * Parameter list for open() is:
+ *
+ * int semantics;
+ * struct sockaddr *peer;
+ * struct sockaddr *local;
+ */
+ LOCATION_SOCKET,
+};
+
+/** A URI opener */
+struct uri_opener {
+ /** URI protocol name
+ *
+ * This is the "scheme" portion of the URI, e.g. "http" or
+ * "file".
+ */
+ const char *scheme;
+ /** Open URI
+ *
+ * @v xfer Data transfer interface
+ * @v uri URI
+ * @ret rc Return status code
+ */
+ int ( * open ) ( struct xfer_interface *xfer, struct uri *uri );
+};
+
+/** Register a URI opener */
+#define __uri_opener __table ( struct uri_opener, uri_openers, 01 )
+
+/** A socket opener */
+struct socket_opener {
+ /** Communication semantics (e.g. SOCK_STREAM) */
+ int semantics;
+ /** Address family (e.g. AF_INET) */
+ int family;
+ /** Open socket
+ *
+ * @v xfer Data transfer interface
+ * @v peer Peer socket address
+ * @v local Local socket address, or NULL
+ * @ret rc Return status code
+ */
+ int ( * open ) ( struct xfer_interface *xfer, struct sockaddr *peer,
+ struct sockaddr *local );
+};
+
+/** Register a socket opener */
+#define __socket_opener __table ( struct socket_opener, socket_openers, 01 )
+
+extern int xfer_open_uri ( struct xfer_interface *xfer, struct uri *uri );
+extern int xfer_open_uri_string ( struct xfer_interface *xfer,
+ const char *uri_string );
+extern int xfer_open_named_socket ( struct xfer_interface *xfer,
+ int semantics, struct sockaddr *peer,
+ const char *name, struct sockaddr *local );
+extern int xfer_open_socket ( struct xfer_interface *xfer, int semantics,
+ struct sockaddr *peer, struct sockaddr *local );
+extern int xfer_vopen ( struct xfer_interface *xfer, int type, va_list args );
+extern int xfer_open ( struct xfer_interface *xfer, int type, ... );
+
+#endif /* _GPXE_OPEN_H */
diff --git a/gpxe/src/include/gpxe/pci.h b/gpxe/src/include/gpxe/pci.h
new file mode 100644
index 00000000..b5c417c9
--- /dev/null
+++ b/gpxe/src/include/gpxe/pci.h
@@ -0,0 +1,356 @@
+#ifndef _GPXE_PCI_H
+#define _GPXE_PCI_H
+
+/*
+ * Support for NE2000 PCI clones added David Monro June 1997
+ * Generalised for other PCI NICs by Ken Yap July 1997
+ * PCI support rewritten by Michael Brown 2006
+ *
+ * Most of this is taken from /usr/src/linux/include/linux/pci.h.
+ */
+
+/*
+ * 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, or (at
+ * your option) any later version.
+ */
+
+#include <stdint.h>
+#include <gpxe/device.h>
+#include <gpxe/tables.h>
+#include <pci_io.h>
+#include "pci_ids.h"
+
+/*
+ * PCI constants
+ *
+ */
+
+#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
+#define PCI_COMMAND_MEM 0x2 /* Enable response in mem space */
+#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */
+#define PCI_LATENCY_TIMER 0x0d /* 8 bits */
+#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */
+#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */
+#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */
+#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */
+#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */
+#define PCI_COMMAND_SERR 0x100 /* Enable SERR */
+#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */
+
+
+#define PCI_VENDOR_ID 0x00 /* 16 bits */
+#define PCI_DEVICE_ID 0x02 /* 16 bits */
+#define PCI_COMMAND 0x04 /* 16 bits */
+
+#define PCI_STATUS 0x06 /* 16 bits */
+#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */
+#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */
+#define PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */
+#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */
+#define PCI_STATUS_PARITY 0x100 /* Detected parity error */
+#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */
+#define PCI_STATUS_DEVSEL_FAST 0x000
+#define PCI_STATUS_DEVSEL_MEDIUM 0x200
+#define PCI_STATUS_DEVSEL_SLOW 0x400
+#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */
+#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */
+#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */
+#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */
+#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */
+
+#define PCI_REVISION 0x08 /* 8 bits */
+#define PCI_REVISION_ID 0x08 /* 8 bits */
+#define PCI_CLASS_REVISION 0x08 /* 32 bits */
+#define PCI_CLASS_CODE 0x0b /* 8 bits */
+#define PCI_SUBCLASS_CODE 0x0a /* 8 bits */
+#define PCI_HEADER_TYPE 0x0e /* 8 bits */
+#define PCI_HEADER_TYPE_NORMAL 0
+#define PCI_HEADER_TYPE_BRIDGE 1
+#define PCI_HEADER_TYPE_CARDBUS 2
+
+
+/* Header type 0 (normal devices) */
+#define PCI_CARDBUS_CIS 0x28
+#define PCI_SUBSYSTEM_VENDOR_ID 0x2c
+#define PCI_SUBSYSTEM_ID 0x2e
+
+#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */
+#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits */
+#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits */
+#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */
+#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */
+#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */
+
+#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */
+#define PCI_BASE_ADDRESS_SPACE_IO 0x01
+#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
+
+#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
+#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */
+#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */
+#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */
+#define PCI_BASE_ADDRESS_MEM_MASK (~0x0f)
+#define PCI_BASE_ADDRESS_IO_MASK (~0x03)
+#define PCI_ROM_ADDRESS 0x30 /* 32 bits */
+#define PCI_ROM_ADDRESS_ENABLE 0x01 /* Write 1 to enable ROM,
+ bits 31..11 are address,
+ 10..2 are reserved */
+
+#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */
+
+#define PCI_INTERRUPT_LINE 0x3c /* IRQ number (0-15) */
+#define PCI_INTERRUPT_PIN 0x3d /* IRQ pin on PCI bus (A-D) */
+
+/* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_PRIMARY_BUS 0x18 /* Primary bus number */
+#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */
+#define PCI_SUBORDINATE_BUS 0x1a /* Highest bus number behind the bridge */
+#define PCI_SEC_LATENCY_TIMER 0x1b /* Latency timer for secondary interface */
+#define PCI_IO_BASE 0x1c /* I/O range behind the bridge */
+#define PCI_IO_LIMIT 0x1d
+#define PCI_IO_RANGE_TYPE_MASK 0x0f /* I/O bridging type */
+#define PCI_IO_RANGE_TYPE_16 0x00
+#define PCI_IO_RANGE_TYPE_32 0x01
+#define PCI_IO_RANGE_MASK ~0x0f
+#define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit 14 used */
+#define PCI_MEMORY_BASE 0x20 /* Memory range behind */
+#define PCI_MEMORY_LIMIT 0x22
+#define PCI_MEMORY_RANGE_TYPE_MASK 0x0f
+#define PCI_MEMORY_RANGE_MASK ~0x0f
+#define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */
+#define PCI_PREF_MEMORY_LIMIT 0x26
+#define PCI_PREF_RANGE_TYPE_MASK 0x0f
+#define PCI_PREF_RANGE_TYPE_32 0x00
+#define PCI_PREF_RANGE_TYPE_64 0x01
+#define PCI_PREF_RANGE_MASK ~0x0f
+#define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory range */
+#define PCI_PREF_LIMIT_UPPER32 0x2c
+#define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16 0x32
+/* 0x34 same as for htype 0 */
+/* 0x35-0x3b is reserved */
+#define PCI_ROM_ADDRESS1 0x38 /* Same as PCI_ROM_ADDRESS, but for htype 1 */
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_BRIDGE_CONTROL 0x3e
+#define PCI_BRIDGE_CTL_PARITY 0x01 /* Enable parity detection on secondary interface */
+#define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */
+#define PCI_BRIDGE_CTL_NO_ISA 0x04 /* Disable bridging of ISA ports */
+#define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */
+#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */
+#define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */
+#define PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */
+
+#define PCI_CB_CAPABILITY_LIST 0x14
+
+/* Capability lists */
+
+#define PCI_CAP_LIST_ID 0 /* Capability ID */
+#define PCI_CAP_ID_PM 0x01 /* Power Management */
+#define PCI_CAP_ID_AGP 0x02 /* Accelerated Graphics Port */
+#define PCI_CAP_ID_VPD 0x03 /* Vital Product Data */
+#define PCI_CAP_ID_SLOTID 0x04 /* Slot Identification */
+#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */
+#define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */
+#define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */
+#define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */
+#define PCI_CAP_SIZEOF 4
+
+/* Power Management Registers */
+
+#define PCI_PM_PMC 2 /* PM Capabilities Register */
+#define PCI_PM_CAP_VER_MASK 0x0007 /* Version */
+#define PCI_PM_CAP_PME_CLOCK 0x0008 /* PME clock required */
+#define PCI_PM_CAP_RESERVED 0x0010 /* Reserved field */
+#define PCI_PM_CAP_DSI 0x0020 /* Device specific initialization */
+#define PCI_PM_CAP_AUX_POWER 0x01C0 /* Auxilliary power support mask */
+#define PCI_PM_CAP_D1 0x0200 /* D1 power state support */
+#define PCI_PM_CAP_D2 0x0400 /* D2 power state support */
+#define PCI_PM_CAP_PME 0x0800 /* PME pin supported */
+#define PCI_PM_CAP_PME_MASK 0xF800 /* PME Mask of all supported states */
+#define PCI_PM_CAP_PME_D0 0x0800 /* PME# from D0 */
+#define PCI_PM_CAP_PME_D1 0x1000 /* PME# from D1 */
+#define PCI_PM_CAP_PME_D2 0x2000 /* PME# from D2 */
+#define PCI_PM_CAP_PME_D3 0x4000 /* PME# from D3 (hot) */
+#define PCI_PM_CAP_PME_D3cold 0x8000 /* PME# from D3 (cold) */
+#define PCI_PM_CTRL 4 /* PM control and status register */
+#define PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */
+#define PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */
+#define PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* Data select (??) */
+#define PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* Data scale (??) */
+#define PCI_PM_CTRL_PME_STATUS 0x8000 /* PME pin status */
+#define PCI_PM_PPB_EXTENSIONS 6 /* PPB support extensions (??) */
+#define PCI_PM_PPB_B2_B3 0x40 /* Stop clock when in D3hot (??) */
+#define PCI_PM_BPCC_ENABLE 0x80 /* Bus power/clock control enable (??) */
+#define PCI_PM_DATA_REGISTER 7 /* (??) */
+#define PCI_PM_SIZEOF 8
+
+/* AGP registers */
+
+#define PCI_AGP_VERSION 2 /* BCD version number */
+#define PCI_AGP_RFU 3 /* Rest of capability flags */
+#define PCI_AGP_STATUS 4 /* Status register */
+#define PCI_AGP_STATUS_RQ_MASK 0xff000000 /* Maximum number of requests - 1 */
+#define PCI_AGP_STATUS_SBA 0x0200 /* Sideband addressing supported */
+#define PCI_AGP_STATUS_64BIT 0x0020 /* 64-bit addressing supported */
+#define PCI_AGP_STATUS_FW 0x0010 /* FW transfers supported */
+#define PCI_AGP_STATUS_RATE4 0x0004 /* 4x transfer rate supported */
+#define PCI_AGP_STATUS_RATE2 0x0002 /* 2x transfer rate supported */
+#define PCI_AGP_STATUS_RATE1 0x0001 /* 1x transfer rate supported */
+#define PCI_AGP_COMMAND 8 /* Control register */
+#define PCI_AGP_COMMAND_RQ_MASK 0xff000000 /* Master: Maximum number of requests */
+#define PCI_AGP_COMMAND_SBA 0x0200 /* Sideband addressing enabled */
+#define PCI_AGP_COMMAND_AGP 0x0100 /* Allow processing of AGP transactions */
+#define PCI_AGP_COMMAND_64BIT 0x0020 /* Allow processing of 64-bit addresses */
+#define PCI_AGP_COMMAND_FW 0x0010 /* Force FW transfers */
+#define PCI_AGP_COMMAND_RATE4 0x0004 /* Use 4x rate */
+#define PCI_AGP_COMMAND_RATE2 0x0002 /* Use 2x rate */
+#define PCI_AGP_COMMAND_RATE1 0x0001 /* Use 1x rate */
+#define PCI_AGP_SIZEOF 12
+
+/* Slot Identification */
+
+#define PCI_SID_ESR 2 /* Expansion Slot Register */
+#define PCI_SID_ESR_NSLOTS 0x1f /* Number of expansion slots available */
+#define PCI_SID_ESR_FIC 0x20 /* First In Chassis Flag */
+#define PCI_SID_CHASSIS_NR 3 /* Chassis Number */
+
+/* Message Signalled Interrupts registers */
+
+#define PCI_MSI_FLAGS 2 /* Various flags */
+#define PCI_MSI_FLAGS_64BIT 0x80 /* 64-bit addresses allowed */
+#define PCI_MSI_FLAGS_QSIZE 0x70 /* Message queue size configured */
+#define PCI_MSI_FLAGS_QMASK 0x0e /* Maximum queue size available */
+#define PCI_MSI_FLAGS_ENABLE 0x01 /* MSI feature enabled */
+#define PCI_MSI_RFU 3 /* Rest of capability flags */
+#define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */
+#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
+#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */
+#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */
+
+/** A PCI device ID list entry */
+struct pci_device_id {
+ /** Name */
+ const char *name;
+ /** PCI vendor ID */
+ uint16_t vendor;
+ /** PCI device ID */
+ uint16_t device;
+};
+
+/** Match-anything ID */
+#define PCI_ANY_ID 0xffff
+
+/** A PCI device */
+struct pci_device {
+ /** Generic device */
+ struct device dev;
+ /** Memory base
+ *
+ * This is the physical address of the first valid memory BAR.
+ */
+ unsigned long membase;
+ /**
+ * I/O address
+ *
+ * This is the physical address of the first valid I/O BAR.
+ */
+ unsigned long ioaddr;
+ /** Vendor ID */
+ uint16_t vendor;
+ /** Device ID */
+ uint16_t device;
+ /** Device class */
+ uint32_t class;
+ /** Interrupt number */
+ uint8_t irq;
+ /** Bus number */
+ uint8_t bus;
+ /** Device and function number */
+ uint8_t devfn;
+ /** Driver for this device */
+ struct pci_driver *driver;
+ /** Driver-private data
+ *
+ * Use pci_set_drvdata() and pci_get_drvdata() to access this
+ * field.
+ */
+ void *priv;
+ /** Driver name */
+ const char *driver_name;
+};
+
+/** A PCI driver */
+struct pci_driver {
+ /** PCI ID table */
+ struct pci_device_id *ids;
+ /** Number of entries in PCI ID table */
+ unsigned int id_count;
+ /**
+ * Probe device
+ *
+ * @v pci PCI device
+ * @v id Matching entry in ID table
+ * @ret rc Return status code
+ */
+ int ( * probe ) ( struct pci_device *pci,
+ const struct pci_device_id *id );
+ /**
+ * Remove device
+ *
+ * @v pci PCI device
+ */
+ void ( * remove ) ( struct pci_device *pci );
+};
+
+/** Declare a PCI driver */
+#define __pci_driver __table ( struct pci_driver, pci_drivers, 01 )
+
+#define PCI_DEVFN( slot, func ) ( ( (slot) << 3 ) | (func) )
+#define PCI_SLOT( devfn ) ( ( (devfn) >> 3 ) & 0x1f )
+#define PCI_FUNC( devfn ) ( (devfn) & 0x07 )
+#define PCI_BUSDEVFN( bus, devfn ) ( ( (bus) << 8 ) | (devfn) )
+
+#define PCI_BASE_CLASS( class ) ( (class) >> 16 )
+#define PCI_SUB_CLASS( class ) ( ( (class) >> 8 ) & 0xff )
+#define PCI_PROG_INTF( class ) ( (class) & 0xff )
+
+/*
+ * PCI_ROM is used to build up entries in a struct pci_id array. It
+ * is also parsed by parserom.pl to generate Makefile rules and files
+ * for rom-o-matic.
+ */
+#define PCI_ROM( _vendor, _device, _name, _description ) { \
+ .vendor = _vendor, \
+ .device = _device, \
+ .name = _name, \
+}
+
+extern void adjust_pci_device ( struct pci_device *pci );
+extern unsigned long pci_bar_start ( struct pci_device *pci,
+ unsigned int reg );
+extern int pci_find_capability ( struct pci_device *pci, int capability );
+extern unsigned long pci_bar_size ( struct pci_device *pci, unsigned int reg );
+
+/**
+ * Set PCI driver-private data
+ *
+ * @v pci PCI device
+ * @v priv Private data
+ */
+static inline void pci_set_drvdata ( struct pci_device *pci, void *priv ) {
+ pci->priv = priv;
+}
+
+/**
+ * Get PCI driver-private data
+ *
+ * @v pci PCI device
+ * @ret priv Private data
+ */
+static inline void * pci_get_drvdata ( struct pci_device *pci ) {
+ return pci->priv;
+}
+
+#endif /* _GPXE_PCI_H */
diff --git a/gpxe/src/include/gpxe/pci_ids.h b/gpxe/src/include/gpxe/pci_ids.h
new file mode 100644
index 00000000..075ff96b
--- /dev/null
+++ b/gpxe/src/include/gpxe/pci_ids.h
@@ -0,0 +1,348 @@
+#ifndef _GPXE_PCI_IDS_H
+#define _GPXE_PCI_IDS_H
+
+/*
+ * PCI Class, Vendor and Device IDs
+ *
+ * Please keep sorted.
+ */
+
+/* Device classes and subclasses */
+
+#define PCI_CLASS_NOT_DEFINED 0x0000
+#define PCI_CLASS_NOT_DEFINED_VGA 0x0001
+
+#define PCI_BASE_CLASS_STORAGE 0x01
+#define PCI_CLASS_STORAGE_SCSI 0x0100
+#define PCI_CLASS_STORAGE_IDE 0x0101
+#define PCI_CLASS_STORAGE_FLOPPY 0x0102
+#define PCI_CLASS_STORAGE_IPI 0x0103
+#define PCI_CLASS_STORAGE_RAID 0x0104
+#define PCI_CLASS_STORAGE_OTHER 0x0180
+
+#define PCI_BASE_CLASS_NETWORK 0x02
+#define PCI_CLASS_NETWORK_ETHERNET 0x0200
+#define PCI_CLASS_NETWORK_TOKEN_RING 0x0201
+#define PCI_CLASS_NETWORK_FDDI 0x0202
+#define PCI_CLASS_NETWORK_ATM 0x0203
+#define PCI_CLASS_NETWORK_OTHER 0x0280
+
+#define PCI_BASE_CLASS_DISPLAY 0x03
+#define PCI_CLASS_DISPLAY_VGA 0x0300
+#define PCI_CLASS_DISPLAY_XGA 0x0301
+#define PCI_CLASS_DISPLAY_3D 0x0302
+#define PCI_CLASS_DISPLAY_OTHER 0x0380
+
+#define PCI_BASE_CLASS_MULTIMEDIA 0x04
+#define PCI_CLASS_MULTIMEDIA_VIDEO 0x0400
+#define PCI_CLASS_MULTIMEDIA_AUDIO 0x0401
+#define PCI_CLASS_MULTIMEDIA_PHONE 0x0402
+#define PCI_CLASS_MULTIMEDIA_OTHER 0x0480
+
+#define PCI_BASE_CLASS_MEMORY 0x05
+#define PCI_CLASS_MEMORY_RAM 0x0500
+#define PCI_CLASS_MEMORY_FLASH 0x0501
+#define PCI_CLASS_MEMORY_OTHER 0x0580
+
+#define PCI_BASE_CLASS_BRIDGE 0x06
+#define PCI_CLASS_BRIDGE_HOST 0x0600
+#define PCI_CLASS_BRIDGE_ISA 0x0601
+#define PCI_CLASS_BRIDGE_EISA 0x0602
+#define PCI_CLASS_BRIDGE_MC 0x0603
+#define PCI_CLASS_BRIDGE_PCI 0x0604
+#define PCI_CLASS_BRIDGE_PCMCIA 0x0605
+#define PCI_CLASS_BRIDGE_NUBUS 0x0606
+#define PCI_CLASS_BRIDGE_CARDBUS 0x0607
+#define PCI_CLASS_BRIDGE_RACEWAY 0x0608
+#define PCI_CLASS_BRIDGE_OTHER 0x0680
+
+#define PCI_BASE_CLASS_COMMUNICATION 0x07
+#define PCI_CLASS_COMMUNICATION_SERIAL 0x0700
+#define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701
+#define PCI_CLASS_COMMUNICATION_MULTISERIAL 0x0702
+#define PCI_CLASS_COMMUNICATION_MODEM 0x0703
+#define PCI_CLASS_COMMUNICATION_OTHER 0x0780
+
+#define PCI_BASE_CLASS_SYSTEM 0x08
+#define PCI_CLASS_SYSTEM_PIC 0x0800
+#define PCI_CLASS_SYSTEM_DMA 0x0801
+#define PCI_CLASS_SYSTEM_TIMER 0x0802
+#define PCI_CLASS_SYSTEM_RTC 0x0803
+#define PCI_CLASS_SYSTEM_PCI_HOTPLUG 0x0804
+#define PCI_CLASS_SYSTEM_OTHER 0x0880
+
+#define PCI_BASE_CLASS_INPUT 0x09
+#define PCI_CLASS_INPUT_KEYBOARD 0x0900
+#define PCI_CLASS_INPUT_PEN 0x0901
+#define PCI_CLASS_INPUT_MOUSE 0x0902
+#define PCI_CLASS_INPUT_SCANNER 0x0903
+#define PCI_CLASS_INPUT_GAMEPORT 0x0904
+#define PCI_CLASS_INPUT_OTHER 0x0980
+
+#define PCI_BASE_CLASS_DOCKING 0x0a
+#define PCI_CLASS_DOCKING_GENERIC 0x0a00
+#define PCI_CLASS_DOCKING_OTHER 0x0a80
+
+#define PCI_BASE_CLASS_PROCESSOR 0x0b
+#define PCI_CLASS_PROCESSOR_386 0x0b00
+#define PCI_CLASS_PROCESSOR_486 0x0b01
+#define PCI_CLASS_PROCESSOR_PENTIUM 0x0b02
+#define PCI_CLASS_PROCESSOR_ALPHA 0x0b10
+#define PCI_CLASS_PROCESSOR_POWERPC 0x0b20
+#define PCI_CLASS_PROCESSOR_MIPS 0x0b30
+#define PCI_CLASS_PROCESSOR_CO 0x0b40
+
+#define PCI_BASE_CLASS_SERIAL 0x0c
+#define PCI_CLASS_SERIAL_FIREWIRE 0x0c00
+#define PCI_CLASS_SERIAL_ACCESS 0x0c01
+#define PCI_CLASS_SERIAL_SSA 0x0c02
+#define PCI_CLASS_SERIAL_USB 0x0c03
+#define PCI_CLASS_SERIAL_FIBER 0x0c04
+#define PCI_CLASS_SERIAL_SMBUS 0x0c05
+
+#define PCI_BASE_CLASS_INTELLIGENT 0x0e
+#define PCI_CLASS_INTELLIGENT_I2O 0x0e00
+
+#define PCI_BASE_CLASS_SATELLITE 0x0f
+#define PCI_CLASS_SATELLITE_TV 0x0f00
+#define PCI_CLASS_SATELLITE_AUDIO 0x0f01
+#define PCI_CLASS_SATELLITE_VOICE 0x0f03
+#define PCI_CLASS_SATELLITE_DATA 0x0f04
+
+#define PCI_BASE_CLASS_CRYPT 0x10
+#define PCI_CLASS_CRYPT_NETWORK 0x1000
+#define PCI_CLASS_CRYPT_ENTERTAINMENT 0x1001
+#define PCI_CLASS_CRYPT_OTHER 0x1080
+
+#define PCI_BASE_CLASS_SIGNAL_PROCESSING 0x11
+#define PCI_CLASS_SP_DPIO 0x1100
+#define PCI_CLASS_SP_OTHER 0x1180
+
+#define PCI_CLASS_OTHERS 0xff
+
+/* Vendors */
+
+#define PCI_VENDOR_ID_DYNALINK 0x0675
+#define PCI_VENDOR_ID_BERKOM 0x0871
+#define PCI_VENDOR_ID_COMPAQ 0x0e11
+#define PCI_VENDOR_ID_NCR 0x1000
+#define PCI_VENDOR_ID_LSI_LOGIC 0x1000
+#define PCI_VENDOR_ID_ATI 0x1002
+#define PCI_VENDOR_ID_VLSI 0x1004
+#define PCI_VENDOR_ID_ADL 0x1005
+#define PCI_VENDOR_ID_NS 0x100b
+#define PCI_VENDOR_ID_TSENG 0x100c
+#define PCI_VENDOR_ID_WEITEK 0x100e
+#define PCI_VENDOR_ID_DEC 0x1011
+#define PCI_VENDOR_ID_CIRRUS 0x1013
+#define PCI_VENDOR_ID_IBM 0x1014
+#define PCI_VENDOR_ID_COMPEX2 0x101a
+/* pci.ids says "AT&T GIS (NCR)" */
+#define PCI_VENDOR_ID_WD 0x101c
+#define PCI_VENDOR_ID_AMI 0x101e
+#define PCI_VENDOR_ID_AMD 0x1022
+#define PCI_VENDOR_ID_TRIDENT 0x1023
+#define PCI_VENDOR_ID_AI 0x1025
+#define PCI_VENDOR_ID_DELL 0x1028
+#define PCI_VENDOR_ID_MATROX 0x102B
+#define PCI_VENDOR_ID_CT 0x102c
+#define PCI_VENDOR_ID_MIRO 0x1031
+#define PCI_VENDOR_ID_NEC 0x1033
+#define PCI_VENDOR_ID_FD 0x1036
+#define PCI_VENDOR_ID_SIS 0x1039
+#define PCI_VENDOR_ID_SI 0x1039
+#define PCI_VENDOR_ID_HP 0x103c
+#define PCI_VENDOR_ID_PCTECH 0x1042
+#define PCI_VENDOR_ID_ASUSTEK 0x1043
+#define PCI_VENDOR_ID_DPT 0x1044
+#define PCI_VENDOR_ID_OPTI 0x1045
+#define PCI_VENDOR_ID_ELSA 0x1048
+#define PCI_VENDOR_ID_ELSA 0x1048
+#define PCI_VENDOR_ID_SGS 0x104a
+#define PCI_VENDOR_ID_BUSLOGIC 0x104B
+#define PCI_VENDOR_ID_TI 0x104c
+#define PCI_VENDOR_ID_SONY 0x104d
+#define PCI_VENDOR_ID_OAK 0x104e
+/* Winbond have two vendor IDs! See 0x10ad as well */
+#define PCI_VENDOR_ID_WINBOND2 0x1050
+#define PCI_VENDOR_ID_ANIGMA 0x1051
+#define PCI_VENDOR_ID_EFAR 0x1055
+#define PCI_VENDOR_ID_MOTOROLA 0x1057
+#define PCI_VENDOR_ID_MOTOROLA_OOPS 0x1507
+#define PCI_VENDOR_ID_PROMISE 0x105a
+#define PCI_VENDOR_ID_N9 0x105d
+#define PCI_VENDOR_ID_UMC 0x1060
+#define PCI_VENDOR_ID_X 0x1061
+#define PCI_VENDOR_ID_MYLEX 0x1069
+#define PCI_VENDOR_ID_PICOP 0x1066
+#define PCI_VENDOR_ID_APPLE 0x106b
+#define PCI_VENDOR_ID_YAMAHA 0x1073
+#define PCI_VENDOR_ID_NEXGEN 0x1074
+#define PCI_VENDOR_ID_QLOGIC 0x1077
+#define PCI_VENDOR_ID_CYRIX 0x1078
+#define PCI_VENDOR_ID_LEADTEK 0x107d
+#define PCI_VENDOR_ID_INTERPHASE 0x107e
+#define PCI_VENDOR_ID_CONTAQ 0x1080
+#define PCI_VENDOR_ID_FOREX 0x1083
+#define PCI_VENDOR_ID_OLICOM 0x108d
+#define PCI_VENDOR_ID_SUN 0x108e
+#define PCI_VENDOR_ID_CMD 0x1095
+#define PCI_VENDOR_ID_VISION 0x1098
+#define PCI_VENDOR_ID_BROOKTREE 0x109e
+#define PCI_VENDOR_ID_SIERRA 0x10a8
+#define PCI_VENDOR_ID_SGI 0x10a9
+#define PCI_VENDOR_ID_ACC 0x10aa
+#define PCI_VENDOR_ID_WINBOND 0x10ad
+#define PCI_VENDOR_ID_DATABOOK 0x10b3
+#define PCI_VENDOR_ID_PLX 0x10b5
+#define PCI_VENDOR_ID_MADGE 0x10b6
+#define PCI_VENDOR_ID_3COM 0x10b7
+#define PCI_VENDOR_ID_SMC 0x10b8
+#define PCI_VENDOR_ID_SUNDANCE 0x13F0
+#define PCI_VENDOR_ID_AL 0x10b9
+#define PCI_VENDOR_ID_MITSUBISHI 0x10ba
+#define PCI_VENDOR_ID_SURECOM 0x10bd
+#define PCI_VENDOR_ID_NEOMAGIC 0x10c8
+#define PCI_VENDOR_ID_ASP 0x10cd
+#define PCI_VENDOR_ID_MACRONIX 0x10d9
+#define PCI_VENDOR_ID_TCONRAD 0x10da
+#define PCI_VENDOR_ID_CERN 0x10dc
+#define PCI_VENDOR_ID_NVIDIA 0x10de
+#define PCI_VENDOR_ID_IMS 0x10e0
+#define PCI_VENDOR_ID_TEKRAM2 0x10e1
+#define PCI_VENDOR_ID_TUNDRA 0x10e3
+#define PCI_VENDOR_ID_AMCC 0x10e8
+#define PCI_VENDOR_ID_INTERG 0x10ea
+#define PCI_VENDOR_ID_REALTEK 0x10ec
+#define PCI_VENDOR_ID_XILINX 0x10ee
+#define PCI_VENDOR_ID_TRUEVISION 0x10fa
+#define PCI_VENDOR_ID_INIT 0x1101
+#define PCI_VENDOR_ID_CREATIVE 0x1102
+/* duplicate: ECTIVA */
+#define PCI_VENDOR_ID_ECTIVA 0x1102
+/* duplicate: CREATIVE */
+#define PCI_VENDOR_ID_TTI 0x1103
+#define PCI_VENDOR_ID_VIA 0x1106
+#define PCI_VENDOR_ID_VIATEC 0x1106
+#define PCI_VENDOR_ID_SIEMENS 0x110A
+#define PCI_VENDOR_ID_SMC2 0x1113
+#define PCI_VENDOR_ID_VORTEX 0x1119
+#define PCI_VENDOR_ID_EF 0x111a
+#define PCI_VENDOR_ID_IDT 0x111d
+#define PCI_VENDOR_ID_FORE 0x1127
+#define PCI_VENDOR_ID_IMAGINGTECH 0x112f
+#define PCI_VENDOR_ID_PHILIPS 0x1131
+#define PCI_VENDOR_ID_EICON 0x1133
+#define PCI_VENDOR_ID_CYCLONE 0x113c
+#define PCI_VENDOR_ID_ALLIANCE 0x1142
+#define PCI_VENDOR_ID_SYSKONNECT 0x1148
+#define PCI_VENDOR_ID_VMIC 0x114a
+#define PCI_VENDOR_ID_DIGI 0x114f
+#define PCI_VENDOR_ID_MUTECH 0x1159
+#define PCI_VENDOR_ID_XIRCOM 0x115d
+#define PCI_VENDOR_ID_RENDITION 0x1163
+#define PCI_VENDOR_ID_SERVERWORKS 0x1166
+#define PCI_VENDOR_ID_SBE 0x1176
+#define PCI_VENDOR_ID_TOSHIBA 0x1179
+#define PCI_VENDOR_ID_RICOH 0x1180
+#define PCI_VENDOR_ID_DLINK 0x1186
+#define PCI_VENDOR_ID_ARTOP 0x1191
+#define PCI_VENDOR_ID_ZEITNET 0x1193
+#define PCI_VENDOR_ID_OMEGA 0x119b
+#define PCI_VENDOR_ID_FUJITSU_ME 0x119e
+#define PCI_SUBVENDOR_ID_KEYSPAN 0x11a9
+#define PCI_VENDOR_ID_GALILEO 0x11ab
+#define PCI_VENDOR_ID_LINKSYS 0x11ad
+#define PCI_VENDOR_ID_LITEON 0x11ad
+#define PCI_VENDOR_ID_V3 0x11b0
+#define PCI_VENDOR_ID_NP 0x11bc
+#define PCI_VENDOR_ID_ATT 0x11c1
+#define PCI_VENDOR_ID_SPECIALIX 0x11cb
+#define PCI_VENDOR_ID_AURAVISION 0x11d1
+#define PCI_VENDOR_ID_ANALOG_DEVICES 0x11d4
+#define PCI_VENDOR_ID_IKON 0x11d5
+#define PCI_VENDOR_ID_ZORAN 0x11de
+#define PCI_VENDOR_ID_KINETIC 0x11f4
+#define PCI_VENDOR_ID_COMPEX 0x11f6
+#define PCI_VENDOR_ID_RP 0x11fe
+#define PCI_VENDOR_ID_CYCLADES 0x120e
+#define PCI_VENDOR_ID_ESSENTIAL 0x120f
+#define PCI_VENDOR_ID_O2 0x1217
+#define PCI_VENDOR_ID_3DFX 0x121a
+#define PCI_VENDOR_ID_SIGMADES 0x1236
+#define PCI_VENDOR_ID_CCUBE 0x123f
+#define PCI_VENDOR_ID_AVM 0x1244
+#define PCI_VENDOR_ID_DIPIX 0x1246
+#define PCI_VENDOR_ID_STALLION 0x124d
+#define PCI_VENDOR_ID_OPTIBASE 0x1255
+#define PCI_VENDOR_ID_ESS 0x125d
+#define PCI_VENDOR_ID_HARRIS 0x1260
+#define PCI_VENDOR_ID_SATSAGEM 0x1267
+#define PCI_VENDOR_ID_HUGHES 0x1273
+#define PCI_VENDOR_ID_ENSONIQ 0x1274
+#define PCI_VENDOR_ID_ROCKWELL 0x127A
+#define PCI_VENDOR_ID_DAVICOM 0x1282
+#define PCI_VENDOR_ID_ITE 0x1283
+/* formerly Platform Tech */
+#define PCI_VENDOR_ID_ESS_OLD 0x1285
+#define PCI_VENDOR_ID_ALTEON 0x12ae
+#define PCI_VENDOR_ID_USR 0x12B9
+#define PCI_VENDOR_ID_HOLTEK 0x12c3
+#define PCI_SUBVENDOR_ID_CONNECT_TECH 0x12c4
+#define PCI_VENDOR_ID_PICTUREL 0x12c5
+#define PCI_VENDOR_ID_NVIDIA_SGS 0x12d2
+#define PCI_SUBVENDOR_ID_CHASE_PCIFAST 0x12E0
+#define PCI_SUBVENDOR_ID_CHASE_PCIRAS 0x124D
+#define PCI_VENDOR_ID_AUREAL 0x12eb
+#define PCI_VENDOR_ID_CBOARDS 0x1307
+#define PCI_VENDOR_ID_SIIG 0x131f
+#define PCI_VENDOR_ID_ADMTEK 0x1317
+#define PCI_VENDOR_ID_DOMEX 0x134a
+#define PCI_VENDOR_ID_QUATECH 0x135C
+#define PCI_VENDOR_ID_SEALEVEL 0x135e
+#define PCI_VENDOR_ID_HYPERCOPE 0x1365
+#define PCI_VENDOR_ID_KAWASAKI 0x136b
+#define PCI_VENDOR_ID_LMC 0x1376
+#define PCI_VENDOR_ID_NETGEAR 0x1385
+#define PCI_VENDOR_ID_APPLICOM 0x1389
+#define PCI_VENDOR_ID_MOXA 0x1393
+#define PCI_VENDOR_ID_CCD 0x1397
+#define PCI_VENDOR_ID_MICROGATE 0x13c0
+#define PCI_VENDOR_ID_3WARE 0x13C1
+#define PCI_VENDOR_ID_ABOCOM 0x13D1
+#define PCI_VENDOR_ID_CMEDIA 0x13f6
+#define PCI_VENDOR_ID_LAVA 0x1407
+#define PCI_VENDOR_ID_TIMEDIA 0x1409
+#define PCI_VENDOR_ID_OXSEMI 0x1415
+#define PCI_VENDOR_ID_AIRONET 0x14b9
+#define PCI_VENDOR_ID_TITAN 0x14D2
+#define PCI_VENDOR_ID_PANACOM 0x14d4
+#define PCI_VENDOR_ID_BROADCOM 0x14e4
+#define PCI_VENDOR_ID_SYBA 0x1592
+#define PCI_VENDOR_ID_MORETON 0x15aa
+#define PCI_VENDOR_ID_ZOLTRIX 0x15b0
+#define PCI_VENDOR_ID_PDC 0x15e9
+#define PCI_VENDOR_ID_FSC 0x1734
+#define PCI_VENDOR_ID_SYMPHONY 0x1c1c
+#define PCI_VENDOR_ID_TEKRAM 0x1de1
+#define PCI_VENDOR_ID_3DLABS 0x3d3d
+#define PCI_VENDOR_ID_AVANCE 0x4005
+#define PCI_VENDOR_ID_AKS 0x416c
+#define PCI_VENDOR_ID_NETVIN 0x4a14
+#define PCI_VENDOR_ID_S3 0x5333
+#define PCI_VENDOR_ID_DCI 0x6666
+#define PCI_VENDOR_ID_GENROCO 0x5555
+#define PCI_VENDOR_ID_INTEL 0x8086
+#define PCI_VENDOR_ID_COMPUTONE 0x8e0e
+#define PCI_SUBVENDOR_ID_COMPUTONE 0x8e0e
+#define PCI_VENDOR_ID_KTI 0x8e2e
+#define PCI_VENDOR_ID_ADAPTEC 0x9004
+#define PCI_VENDOR_ID_ADAPTEC2 0x9005
+#define PCI_VENDOR_ID_ATRONICS 0x907f
+#define PCI_VENDOR_ID_HOLTEK2 0x9412
+#define PCI_VENDOR_ID_NETMOS 0x9710
+#define PCI_SUBVENDOR_ID_EXSYS 0xd84d
+#define PCI_VENDOR_ID_TIGERJET 0xe159
+#define PCI_VENDOR_ID_ARK 0xedd8
+
+#endif /* _GPXE_PCI_IDS_H */
diff --git a/gpxe/src/include/gpxe/posix_io.h b/gpxe/src/include/gpxe/posix_io.h
new file mode 100644
index 00000000..9984db00
--- /dev/null
+++ b/gpxe/src/include/gpxe/posix_io.h
@@ -0,0 +1,85 @@
+#ifndef _GPXE_POSIX_IO_H
+#define _GPXE_POSIX_IO_H
+
+/** @file
+ *
+ * POSIX-like I/O
+ *
+ */
+
+#include <stdint.h>
+#include <gpxe/uaccess.h>
+
+/** Minimum file descriptor that will ever be allocated */
+#define POSIX_FD_MIN ( 1 )
+
+/** Maximum file descriptor that will ever be allocated */
+#define POSIX_FD_MAX ( 31 )
+
+/** File descriptor set as used for select() */
+typedef uint32_t fd_set;
+
+extern int open ( const char *uri_string );
+extern ssize_t read_user ( int fd, userptr_t buffer,
+ off_t offset, size_t len );
+extern int select ( fd_set *readfds, int wait );
+extern ssize_t fsize ( int fd );
+extern int close ( int fd );
+
+/**
+ * Zero a file descriptor set
+ *
+ * @v set File descriptor set
+ */
+static inline __attribute__ (( always_inline )) void
+FD_ZERO ( fd_set *set ) {
+ *set = 0;
+}
+
+/**
+ * Set a bit within a file descriptor set
+ *
+ * @v fd File descriptor
+ * @v set File descriptor set
+ */
+static inline __attribute__ (( always_inline )) void
+FD_SET ( int fd, fd_set *set ) {
+ *set |= ( 1 << fd );
+}
+
+/**
+ * Clear a bit within a file descriptor set
+ *
+ * @v fd File descriptor
+ * @v set File descriptor set
+ */
+static inline __attribute__ (( always_inline )) void
+FD_CLR ( int fd, fd_set *set ) {
+ *set &= ~( 1 << fd );
+}
+
+/**
+ * Test a bit within a file descriptor set
+ *
+ * @v fd File descriptor
+ * @v set File descriptor set
+ * @ret is_set Corresponding bit is set
+ */
+static inline __attribute__ (( always_inline )) int
+FD_ISSET ( int fd, fd_set *set ) {
+ return ( *set & ( 1 << fd ) );
+}
+
+/**
+ * Read data from file
+ *
+ * @v fd File descriptor
+ * @v buf Data buffer
+ * @v len Maximum length to read
+ * @ret len Actual length read, or negative error number
+ */
+static inline ssize_t read ( int fd, void *buf, size_t len ) {
+ return read_user ( fd, virt_to_user ( buf ), 0, len );
+}
+
+#endif /* _GPXE_POSIX_IO_H */
diff --git a/gpxe/src/include/gpxe/process.h b/gpxe/src/include/gpxe/process.h
new file mode 100644
index 00000000..8d9b109a
--- /dev/null
+++ b/gpxe/src/include/gpxe/process.h
@@ -0,0 +1,75 @@
+#ifndef _GPXE_PROCESS_H
+#define _GPXE_PROCESS_H
+
+/** @file
+ *
+ * Processes
+ *
+ */
+
+#include <gpxe/list.h>
+#include <gpxe/refcnt.h>
+#include <gpxe/tables.h>
+
+/** A process */
+struct process {
+ /** List of processes */
+ struct list_head list;
+ /**
+ * Single-step the process
+ *
+ * This method should execute a single step of the process.
+ * Returning from this method is isomorphic to yielding the
+ * CPU to another process.
+ */
+ void ( * step ) ( struct process *process );
+ /** Reference counter
+ *
+ * If this interface is not part of a reference-counted
+ * object, this field may be NULL.
+ */
+ struct refcnt *refcnt;
+};
+
+extern void process_add ( struct process *process );
+extern void process_del ( struct process *process );
+extern void step ( void );
+
+/**
+ * Initialise process without adding to process list
+ *
+ * @v process Process
+ * @v step Process' step() method
+ */
+static inline __attribute__ (( always_inline )) void
+process_init_stopped ( struct process *process,
+ void ( * step ) ( struct process *process ),
+ struct refcnt *refcnt ) {
+ process->step = step;
+ process->refcnt = refcnt;
+}
+
+/**
+ * Initialise process and add to process list
+ *
+ * @v process Process
+ * @v step Process' step() method
+ */
+static inline __attribute__ (( always_inline )) void
+process_init ( struct process *process,
+ void ( * step ) ( struct process *process ),
+ struct refcnt *refcnt ) {
+ process_init_stopped ( process, step, refcnt );
+ process_add ( process );
+}
+
+/**
+ * Declare a permanent process
+ *
+ * Permanent processes will be automatically added to the process list
+ * at initialisation time.
+ */
+#define __permanent_process \
+ __table ( struct process, processes, 01 )
+
+#endif /* _GPXE_PROCESS_H */
diff --git a/gpxe/src/include/gpxe/profile.h b/gpxe/src/include/gpxe/profile.h
new file mode 100644
index 00000000..d46ca05a
--- /dev/null
+++ b/gpxe/src/include/gpxe/profile.h
@@ -0,0 +1,78 @@
+#ifndef _GPXE_PROFILE_H
+#define _GPXE_PROFILE_H
+
+/** @file
+ *
+ * Profiling
+ *
+ */
+
+#include <stdint.h>
+
+/**
+ * A data structure for storing profiling information
+ */
+union profiler {
+ /** Timestamp (in CPU-specific "ticks") */
+ uint64_t timestamp;
+ /** Registers returned by rdtsc.
+ *
+ * This part should really be architecture-specific code.
+ */
+ struct {
+ uint32_t eax;
+ uint32_t edx;
+ } rdtsc;
+};
+
+/**
+ * Static per-object profiler, for use with simple_profile()
+ */
+static union profiler simple_profiler;
+
+/**
+ * Perform profiling
+ *
+ * @v profiler Profiler data structure
+ * @ret delta Elapsed ticks since last call to profile().
+ *
+ * Call profile() both before and after the code you wish to measure.
+ * The "after" call will return the measurement. For example:
+ *
+ * @code
+ *
+ * profile ( &profiler );
+ * ... do something here ...
+ * printf ( "It took %ld ticks to execute\n", profile ( &profiler ) );
+ *
+ * @endcode
+ */
+static inline __attribute__ (( always_inline )) unsigned long
+profile ( union profiler *profiler ) {
+ uint64_t last_timestamp = profiler->timestamp;
+
+ __asm__ __volatile__ ( "rdtsc" :
+ "=a" ( profiler->rdtsc.eax ),
+ "=d" ( profiler->rdtsc.edx ) );
+ return ( profiler->timestamp - last_timestamp );
+}
+
+/**
+ * Perform profiling
+ *
+ * @ret delta Elapsed ticks since last call to profile().
+ *
+ * When you only need one profiler, you can avoid the hassle of
+ * creating your own @c profiler data structure by using
+ * simple_profile() instead.
+ *
+ * simple_profile() is equivalent to profile(&simple_profiler), where
+ * @c simple_profiler is a @c profiler data structure that is static
+ * to each object which includes @c profile.h.
+ */
+static inline __attribute__ (( always_inline )) unsigned long
+simple_profile ( void ) {
+ return profile ( &simple_profiler );
+}
+
+#endif /* _GPXE_PROFILE_H */
diff --git a/gpxe/src/include/gpxe/ramdisk.h b/gpxe/src/include/gpxe/ramdisk.h
new file mode 100644
index 00000000..4a77f05e
--- /dev/null
+++ b/gpxe/src/include/gpxe/ramdisk.h
@@ -0,0 +1,22 @@
+#ifndef _GPXE_RAMDISK_H
+#define _GPXE_RAMDISK_H
+
+/**
+ * @file
+ *
+ * RAM disks
+ *
+ */
+
+#include <gpxe/uaccess.h>
+#include <gpxe/blockdev.h>
+
+struct ramdisk {
+ struct block_device blockdev;
+ userptr_t data;
+};
+
+extern int init_ramdisk ( struct ramdisk *ramdisk, userptr_t data, size_t len,
+ unsigned int blksize );
+
+#endif /* _GPXE_RAMDISK_H */
diff --git a/gpxe/src/include/gpxe/rarp.h b/gpxe/src/include/gpxe/rarp.h
new file mode 100644
index 00000000..81e03bde
--- /dev/null
+++ b/gpxe/src/include/gpxe/rarp.h
@@ -0,0 +1,14 @@
+#ifndef _GPXE_RARP_H
+#define _GPXE_RARP_H
+
+/** @file
+ *
+ * Reverse Address Resolution Protocol
+ *
+ */
+
+struct net_protocol;
+
+extern struct net_protocol rarp_protocol;
+
+#endif /* _GPXE_RARP_H */
diff --git a/gpxe/src/include/gpxe/refcnt.h b/gpxe/src/include/gpxe/refcnt.h
new file mode 100644
index 00000000..68e0fd4b
--- /dev/null
+++ b/gpxe/src/include/gpxe/refcnt.h
@@ -0,0 +1,44 @@
+#ifndef _GPXE_REFCNT_H
+#define _GPXE_REFCNT_H
+
+/** @file
+ *
+ * Reference counting
+ *
+ */
+
+/**
+ * A reference counter
+ *
+ * This data structure is designed to be embedded within a
+ * reference-counted object.
+ *
+ * Reference-counted objects are freed when their reference count
+ * drops below zero. This means that a freshly allocated-and-zeroed
+ * reference-counted object will be freed on the first call to
+ * ref_put().
+ */
+struct refcnt {
+ /** Current reference count
+ *
+ * When this count is decremented below zero, the free()
+ * method will be called.
+ */
+ int refcnt;
+ /** Free containing object
+ *
+ * This method is called when the reference count is
+ * decremented below zero.
+ *
+ * If this method is left NULL, the standard library free()
+ * function will be called. The upshot of this is that you
+ * may omit the free() method if the @c refcnt object is the
+ * first element of your reference-counted struct.
+ */
+ void ( * free ) ( struct refcnt *refcnt );
+};
+
+extern struct refcnt * ref_get ( struct refcnt *refcnt );
+extern void ref_put ( struct refcnt *refcnt );
+
+#endif /* _GPXE_REFCNT_H */
diff --git a/gpxe/src/include/gpxe/resolv.h b/gpxe/src/include/gpxe/resolv.h
new file mode 100644
index 00000000..7c1ee6e2
--- /dev/null
+++ b/gpxe/src/include/gpxe/resolv.h
@@ -0,0 +1,166 @@
+#ifndef _GPXE_RESOLV_H
+#define _GPXE_RESOLV_H
+
+/** @file
+ *
+ * Name resolution
+ *
+ */
+
+#include <gpxe/refcnt.h>
+#include <gpxe/interface.h>
+#include <gpxe/tables.h>
+
+struct sockaddr;
+struct resolv_interface;
+
+/** Name resolution interface operations */
+struct resolv_interface_operations {
+ /** Name resolution completed
+ *
+ * @v resolv Name resolution interface
+ * @v sa Completed socket address (if successful)
+ * @v rc Final status code
+ */
+ void ( * done ) ( struct resolv_interface *resolv,
+ struct sockaddr *sa, int rc );
+};
+
+/** A name resolution interface */
+struct resolv_interface {
+ /** Generic object communication interface */
+ struct interface intf;
+ /** Operations for received messages */
+ struct resolv_interface_operations *op;
+};
+
+extern struct resolv_interface null_resolv;
+extern struct resolv_interface_operations null_resolv_ops;
+
+/**
+ * Initialise a name resolution interface
+ *
+ * @v resolv Name resolution interface
+ * @v op Name resolution interface operations
+ * @v refcnt Containing object reference counter, or NULL
+ */
+static inline void resolv_init ( struct resolv_interface *resolv,
+ struct resolv_interface_operations *op,
+ struct refcnt *refcnt ) {
+ resolv->intf.dest = &null_resolv.intf;
+ resolv->intf.refcnt = refcnt;
+ resolv->op = op;
+}
+
+/**
+ * Get name resolution interface from generic object communication interface
+ *
+ * @v intf Generic object communication interface
+ * @ret resolv Name resolution interface
+ */
+static inline __attribute__ (( always_inline )) struct resolv_interface *
+intf_to_resolv ( struct interface *intf ) {
+ return container_of ( intf, struct resolv_interface, intf );
+}
+
+/**
+ * Get reference to destination name resolution interface
+ *
+ * @v resolv Name resolution interface
+ * @ret dest Destination interface
+ */
+static inline __attribute__ (( always_inline )) struct resolv_interface *
+resolv_get_dest ( struct resolv_interface *resolv ) {
+ return intf_to_resolv ( intf_get ( resolv->intf.dest ) );
+}
+
+/**
+ * Drop reference to name resolution interface
+ *
+ * @v resolv name resolution interface
+ */
+static inline __attribute__ (( always_inline )) void
+resolv_put ( struct resolv_interface *resolv ) {
+ intf_put ( &resolv->intf );
+}
+
+/**
+ * Plug a name resolution interface into a new destination interface
+ *
+ * @v resolv Name resolution interface
+ * @v dest New destination interface
+ */
+static inline __attribute__ (( always_inline )) void
+resolv_plug ( struct resolv_interface *resolv, struct resolv_interface *dest ) {
+ plug ( &resolv->intf, &dest->intf );
+}
+
+/**
+ * Plug two name resolution interfaces together
+ *
+ * @v a Name resolution interface A
+ * @v b Name resolution interface B
+ */
+static inline __attribute__ (( always_inline )) void
+resolv_plug_plug ( struct resolv_interface *a, struct resolv_interface *b ) {
+ plug_plug ( &a->intf, &b->intf );
+}
+
+/**
+ * Unplug a name resolution interface
+ *
+ * @v resolv Name resolution interface
+ */
+static inline __attribute__ (( always_inline )) void
+resolv_unplug ( struct resolv_interface *resolv ) {
+ plug ( &resolv->intf, &null_resolv.intf );
+}
+
+/**
+ * Stop using a name resolution interface
+ *
+ * @v resolv Name resolution interface
+ *
+ * After calling this method, no further messages will be received via
+ * the interface.
+ */
+static inline void resolv_nullify ( struct resolv_interface *resolv ) {
+ resolv->op = &null_resolv_ops;
+};
+
+/** A name resolver */
+struct resolver {
+ /** Name of this resolver (e.g. "DNS") */
+ const char *name;
+ /** Start name resolution
+ *
+ * @v resolv Name resolution interface
+ * @v name Name to resolve
+ * @v sa Socket address to complete
+ * @ret rc Return status code
+ */
+ int ( * resolv ) ( struct resolv_interface *resolv, const char *name,
+ struct sockaddr *sa );
+};
+
+/** Numeric resolver priority */
+#define RESOLV_NUMERIC 01
+
+/** Normal resolver priority */
+#define RESOLV_NORMAL 02
+
+/** Register as a name resolver */
+#define __resolver( resolv_order ) \
+ __table ( struct resolver, resolvers, resolv_order )
+
+extern void resolv_done ( struct resolv_interface *resolv,
+ struct sockaddr *sa, int rc );
+extern void ignore_resolv_done ( struct resolv_interface *resolv,
+ struct sockaddr *sa, int rc );
+extern struct resolv_interface_operations null_resolv_ops;
+extern struct resolv_interface null_resolv;
+
+extern int resolv ( struct resolv_interface *resolv, const char *name,
+ struct sockaddr *sa );
+
+#endif /* _GPXE_RESOLV_H */
diff --git a/gpxe/src/include/gpxe/retry.h b/gpxe/src/include/gpxe/retry.h
new file mode 100644
index 00000000..e71e7b3b
--- /dev/null
+++ b/gpxe/src/include/gpxe/retry.h
@@ -0,0 +1,52 @@
+#ifndef _GPXE_RETRY_H
+#define _GPXE_RETRY_H
+
+/** @file
+ *
+ * Retry timers
+ *
+ */
+
+#include <gpxe/list.h>
+
+/** A retry timer */
+struct retry_timer {
+ /** List of active timers */
+ struct list_head list;
+ /** Timeout value (in ticks) */
+ unsigned long timeout;
+ /** Start time (in ticks)
+ *
+ * A start time of zero indicates a stopped timer.
+ */
+ unsigned long start;
+ /** Retry count */
+ unsigned int count;
+ /** Timer expired callback
+ *
+ * @v timer Retry timer
+ * @v fail Failure indicator
+ *
+ * The timer will already be stopped when this method is
+ * called. The failure indicator will be True if the retry
+ * timeout has already exceeded @c MAX_TIMEOUT.
+ */
+ void ( * expired ) ( struct retry_timer *timer, int over );
+};
+
+extern void start_timer ( struct retry_timer *timer );
+extern void start_timer_nodelay ( struct retry_timer *timer );
+extern void stop_timer ( struct retry_timer *timer );
+
+/**
+ * Test to see if timer is currently running
+ *
+ * @v timer Retry timer
+ * @ret running Non-zero if timer is running
+ */
+static inline __attribute__ (( always_inline )) unsigned long
+timer_running ( struct retry_timer *timer ) {
+ return ( timer->start );
+}
+
+#endif /* _GPXE_RETRY_H */
diff --git a/gpxe/src/include/gpxe/rsa.h b/gpxe/src/include/gpxe/rsa.h
new file mode 100644
index 00000000..ce15cfa0
--- /dev/null
+++ b/gpxe/src/include/gpxe/rsa.h
@@ -0,0 +1,10 @@
+#ifndef _GPXE_RSA_H
+#define _GPXE_RSA_H
+
+struct crypto_algorithm;
+
+extern struct crypto_algorithm rsa_algorithm;
+
+#include "crypto/axtls/crypto.h"
+
+#endif /* _GPXE_RSA_H */
diff --git a/gpxe/src/include/gpxe/scsi.h b/gpxe/src/include/gpxe/scsi.h
new file mode 100644
index 00000000..e820117b
--- /dev/null
+++ b/gpxe/src/include/gpxe/scsi.h
@@ -0,0 +1,270 @@
+#ifndef _GPXE_SCSI_H
+#define _GPXE_SCSI_H
+
+#include <stdint.h>
+#include <gpxe/blockdev.h>
+#include <gpxe/uaccess.h>
+#include <gpxe/refcnt.h>
+
+/** @file
+ *
+ * SCSI devices
+ *
+ */
+
+/**
+ * @defgroup scsiops SCSI operation codes
+ * @{
+ */
+
+#define SCSI_OPCODE_READ_10 0x28 /**< READ (10) */
+#define SCSI_OPCODE_READ_16 0x88 /**< READ (16) */
+#define SCSI_OPCODE_WRITE_10 0x2a /**< WRITE (10) */
+#define SCSI_OPCODE_WRITE_16 0x8a /**< WRITE (16) */
+#define SCSI_OPCODE_READ_CAPACITY_10 0x25 /**< READ CAPACITY (10) */
+#define SCSI_OPCODE_SERVICE_ACTION_IN 0x9e /**< SERVICE ACTION IN */
+#define SCSI_SERVICE_ACTION_READ_CAPACITY_16 0x10 /**< READ CAPACITY (16) */
+
+/** @} */
+
+/**
+ * @defgroup scsiflags SCSI flags
+ * @{
+ */
+
+#define SCSI_FL_FUA_NV 0x02 /**< Force unit access to NVS */
+#define SCSI_FL_FUA 0x08 /**< Force unit access */
+#define SCSI_FL_DPO 0x10 /**< Disable cache page out */
+
+/** @} */
+
+/**
+ * @defgroup scsicdbs SCSI command data blocks
+ * @{
+ */
+
+/** A SCSI "READ (10)" CDB */
+struct scsi_cdb_read_10 {
+ /** Opcode (0x28) */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Start address
+ *
+ * This is a logical block number, in big-endian order.
+ */
+ uint32_t lba;
+ /** Group number */
+ uint8_t group;
+ /** Transfer length
+ *
+ * This is a logical block count, in big-endian order.
+ */
+ uint16_t len;
+ /** Control byte */
+ uint8_t control;
+} __attribute__ (( packed ));
+
+/** A SCSI "READ (16)" CDB */
+struct scsi_cdb_read_16 {
+ /** Opcode (0x88) */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Start address
+ *
+ * This is a logical block number, in big-endian order.
+ */
+ uint64_t lba;
+ /** Transfer length
+ *
+ * This is a logical block count, in big-endian order.
+ */
+ uint32_t len;
+ /** Group number */
+ uint8_t group;
+ /** Control byte */
+ uint8_t control;
+} __attribute__ (( packed ));
+
+/** A SCSI "WRITE (10)" CDB */
+struct scsi_cdb_write_10 {
+ /** Opcode (0x2a) */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Start address
+ *
+ * This is a logical block number, in big-endian order.
+ */
+ uint32_t lba;
+ /** Group number */
+ uint8_t group;
+ /** Transfer length
+ *
+ * This is a logical block count, in big-endian order.
+ */
+ uint16_t len;
+ /** Control byte */
+ uint8_t control;
+} __attribute__ (( packed ));
+
+/** A SCSI "WRITE (16)" CDB */
+struct scsi_cdb_write_16 {
+ /** Opcode (0x8a) */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Start address
+ *
+ * This is a logical block number, in big-endian order.
+ */
+ uint64_t lba;
+ /** Transfer length
+ *
+ * This is a logical block count, in big-endian order.
+ */
+ uint32_t len;
+ /** Group number */
+ uint8_t group;
+ /** Control byte */
+ uint8_t control;
+} __attribute__ (( packed ));
+
+/** A SCSI "READ CAPACITY (10)" CDB */
+struct scsi_cdb_read_capacity_10 {
+ /** Opcode (0x25) */
+ uint8_t opcode;
+ /** Reserved */
+ uint8_t reserved_a;
+ /** Logical block address
+ *
+ * Applicable only if the PMI bit is set.
+ */
+ uint32_t lba;
+ /** Reserved */
+ uint8_t reserved_b[3];
+ /** Control byte */
+ uint8_t control;
+} __attribute__ (( packed ));
+
+/** SCSI "READ CAPACITY (10)" parameter data */
+struct scsi_capacity_10 {
+ /** Maximum logical block number */
+ uint32_t lba;
+ /** Block length in bytes */
+ uint32_t blksize;
+} __attribute__ (( packed ));
+
+/** A SCSI "READ CAPACITY (16)" CDB */
+struct scsi_cdb_read_capacity_16 {
+ /** Opcode (0x9e) */
+ uint8_t opcode;
+ /** Service action */
+ uint8_t service_action;
+ /** Logical block address
+ *
+ * Applicable only if the PMI bit is set.
+ */
+ uint64_t lba;
+ /** Transfer length
+ *
+ * This is the size of the data-in buffer, in bytes.
+ */
+ uint32_t len;
+ /** Reserved */
+ uint8_t reserved;
+ /** Control byte */
+ uint8_t control;
+} __attribute__ (( packed ));
+
+/** SCSI "READ CAPACITY (16)" parameter data */
+struct scsi_capacity_16 {
+ /** Maximum logical block number */
+ uint64_t lba;
+ /** Block length in bytes */
+ uint32_t blksize;
+ /** Reserved */
+ uint8_t reserved[20];
+} __attribute__ (( packed ));
+
+/** A SCSI Command Data Block */
+union scsi_cdb {
+ struct scsi_cdb_read_10 read10;
+ struct scsi_cdb_read_16 read16;
+ struct scsi_cdb_write_10 write10;
+ struct scsi_cdb_write_16 write16;
+ struct scsi_cdb_read_capacity_10 readcap10;
+ struct scsi_cdb_read_capacity_16 readcap16;
+ unsigned char bytes[16];
+};
+
+/** printf() format for dumping a scsi_cdb */
+#define SCSI_CDB_FORMAT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" \
+ "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
+
+/** printf() parameters for dumping a scsi_cdb */
+#define SCSI_CDB_DATA(cdb) \
+ (cdb).bytes[0], (cdb).bytes[1], (cdb).bytes[2], (cdb).bytes[3], \
+ (cdb).bytes[4], (cdb).bytes[5], (cdb).bytes[6], (cdb).bytes[7], \
+ (cdb).bytes[8], (cdb).bytes[9], (cdb).bytes[10], (cdb).bytes[11], \
+ (cdb).bytes[12], (cdb).bytes[13], (cdb).bytes[14], (cdb).bytes[15]
+
+/** @} */
+
+/** A SCSI command */
+struct scsi_command {
+ /** CDB for this command */
+ union scsi_cdb cdb;
+ /** Data-out buffer (may be NULL) */
+ userptr_t data_out;
+ /** Data-out buffer length
+ *
+ * Must be zero if @c data_out is NULL
+ */
+ size_t data_out_len;
+ /** Data-in buffer (may be NULL) */
+ userptr_t data_in;
+ /** Data-in buffer length
+ *
+ * Must be zero if @c data_in is NULL
+ */
+ size_t data_in_len;
+ /** SCSI status code */
+ uint8_t status;
+ /** SCSI sense response code */
+ uint8_t sense_response;
+};
+
+/** A SCSI device */
+struct scsi_device {
+ /** Block device interface */
+ struct block_device blockdev;
+ /** Logical unit number (LUN)
+ *
+ * This is a four-level LUN as specified by SAM-2, in
+ * big-endian order.
+ */
+ uint64_t lun;
+ /**
+ * Issue SCSI command
+ *
+ * @v scsi SCSI device
+ * @v command SCSI command
+ * @ret rc Return status code
+ *
+ * Note that a successful return status code indicates only
+ * that the SCSI command completed. The caller must check the
+ * status field in the command structure to see if, for
+ * example, the device returned CHECK CONDITION or some other
+ * non-success status code.
+ */
+ int ( * command ) ( struct scsi_device *scsi,
+ struct scsi_command *command );
+ /** Backing device */
+ struct refcnt *backend;
+};
+
+extern int init_scsidev ( struct scsi_device *scsi );
+
+#endif /* _GPXE_SCSI_H */
diff --git a/gpxe/src/include/gpxe/segment.h b/gpxe/src/include/gpxe/segment.h
new file mode 100644
index 00000000..5ab91699
--- /dev/null
+++ b/gpxe/src/include/gpxe/segment.h
@@ -0,0 +1,15 @@
+#ifndef _GPXE_SEGMENT_H
+#define _GPXE_SEGMENT_H
+
+/**
+ * @file
+ *
+ * Executable image segments
+ *
+ */
+
+#include <gpxe/uaccess.h>
+
+extern int prep_segment ( userptr_t segment, size_t filesz, size_t memsz );
+
+#endif /* _GPXE_SEGMENT_H */
diff --git a/gpxe/src/include/gpxe/settings.h b/gpxe/src/include/gpxe/settings.h
new file mode 100644
index 00000000..40825698
--- /dev/null
+++ b/gpxe/src/include/gpxe/settings.h
@@ -0,0 +1,285 @@
+#ifndef _GPXE_SETTINGS_H
+#define _GPXE_SETTINGS_H
+
+/** @file
+ *
+ * Configuration settings
+ *
+ */
+
+#include <stdint.h>
+#include <gpxe/tables.h>
+#include <gpxe/list.h>
+#include <gpxe/refcnt.h>
+#include <gpxe/dhcpopts.h>
+
+struct settings;
+struct in_addr;
+
+/** A setting */
+struct setting {
+ /** Name
+ *
+ * This is the human-readable name for the setting.
+ */
+ const char *name;
+ /** Description */
+ const char *description;
+ /** Setting type
+ *
+ * This identifies the type of setting (e.g. string, IPv4
+ * address, etc.).
+ */
+ struct setting_type *type;
+ /** DHCP option number, if applicable */
+ unsigned int tag;
+};
+
+/** Declare a configuration setting */
+#define __setting __table ( struct setting, settings, 01 )
+
+/** Settings block operations */
+struct settings_operations {
+ /** Store value of setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+ int ( * store ) ( struct settings *settings, struct setting *setting,
+ const void *data, size_t len );
+ /** Fetch value of 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
+ *
+ * The actual length of the setting will be returned even if
+ * the buffer was too small.
+ */
+ int ( * fetch ) ( struct settings *settings, struct setting *setting,
+ void *data, size_t len );
+};
+
+/** A settings block */
+struct settings {
+ /** Reference counter */
+ struct refcnt *refcnt;
+ /** Name */
+ const char *name;
+ /** Parent settings block */
+ struct settings *parent;
+ /** Sibling settings blocks */
+ struct list_head siblings;
+ /** Child settings blocks */
+ struct list_head children;
+ /** Settings block operations */
+ struct settings_operations *op;
+};
+
+/**
+ * A setting type
+ *
+ * This represents a type of setting (e.g. string, IPv4 address,
+ * etc.).
+ */
+struct setting_type {
+ /** Name
+ *
+ * This is the name exposed to the user (e.g. "string").
+ */
+ const char *name;
+ /** Parse and set value of setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v value Formatted setting data
+ * @ret rc Return status code
+ */
+ int ( * storef ) ( struct settings *settings, struct setting *setting,
+ const char *value );
+ /** Fetch and format value of setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to fetch
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+ int ( * fetchf ) ( struct settings *settings, struct setting *setting,
+ char *buf, size_t len );
+};
+
+/** Declare a configuration setting type */
+#define __setting_type \
+ __table ( struct setting_type, setting_types, 01 )
+
+/**
+ * A settings applicator
+ *
+ */
+struct settings_applicator {
+ /** Apply updated settings
+ *
+ * @ret rc Return status code
+ */
+ int ( * apply ) ( void );
+};
+
+/** Declare a settings applicator */
+#define __settings_applicator \
+ __table ( struct settings_applicator, settings_applicators, 01 )
+
+/**
+ * A simple settings block
+ *
+ */
+struct simple_settings {
+ /** Settings block */
+ struct settings settings;
+ /** DHCP options */
+ struct dhcp_options dhcpopts;
+};
+
+extern struct settings_operations simple_settings_operations;
+extern int simple_settings_store ( struct settings *settings,
+ struct setting *setting,
+ const void *data, size_t len );
+extern int simple_settings_fetch ( struct settings *settings,
+ struct setting *setting,
+ void *data, size_t len );
+
+extern int register_settings ( struct settings *settings,
+ struct settings *parent );
+extern void unregister_settings ( struct settings *settings );
+
+extern int store_setting ( struct settings *settings, struct setting *setting,
+ const void *data, size_t len );
+extern int fetch_setting ( struct settings *settings, struct setting *setting,
+ void *data, size_t len );
+extern int fetch_setting_len ( struct settings *settings,
+ struct setting *setting );
+extern int fetch_string_setting ( struct settings *settings,
+ struct setting *setting,
+ char *data, size_t len );
+extern int fetch_ipv4_setting ( struct settings *settings,
+ struct setting *setting, struct in_addr *inp );
+extern int fetch_int_setting ( struct settings *settings,
+ struct setting *setting, long *value );
+extern int fetch_uint_setting ( struct settings *settings,
+ struct setting *setting,
+ unsigned long *value );
+extern long fetch_intz_setting ( struct settings *settings,
+ struct setting *setting );
+extern unsigned long fetch_uintz_setting ( struct settings *settings,
+ struct setting *setting );
+extern int setting_cmp ( struct setting *a, struct setting *b );
+
+extern struct settings * find_child_settings ( struct settings *parent,
+ const char *name );
+extern struct settings * find_settings ( const char *name );
+
+extern int storef_setting ( struct settings *settings,
+ struct setting *setting,
+ const char *value );
+extern int storef_named_setting ( const char *name, const char *value );
+extern int fetchf_named_setting ( const char *name, char *buf, size_t len );
+
+extern struct setting_type setting_type_string __setting_type;
+extern struct setting_type setting_type_ipv4 __setting_type;
+extern struct setting_type setting_type_int8 __setting_type;
+extern struct setting_type setting_type_int16 __setting_type;
+extern struct setting_type setting_type_int32 __setting_type;
+extern struct setting_type setting_type_uint8 __setting_type;
+extern struct setting_type setting_type_uint16 __setting_type;
+extern struct setting_type setting_type_uint32 __setting_type;
+extern struct setting_type setting_type_hex __setting_type;
+
+extern struct setting ip_setting __setting;
+extern struct setting netmask_setting __setting;
+extern struct setting gateway_setting __setting;
+extern struct setting dns_setting __setting;
+extern struct setting hostname_setting __setting;
+extern struct setting filename_setting __setting;
+extern struct setting root_path_setting __setting;
+extern struct setting username_setting __setting;
+extern struct setting password_setting __setting;
+extern struct setting priority_setting __setting;
+extern struct setting bios_drive_setting __setting;
+
+/**
+ * Initialise a settings block
+ *
+ * @v settings Settings block
+ * @v op Settings block operations
+ * @v refcnt Containing object reference counter, or NULL
+ * @v name Settings block name
+ */
+static inline void settings_init ( struct settings *settings,
+ struct settings_operations *op,
+ struct refcnt *refcnt,
+ const char *name ) {
+ INIT_LIST_HEAD ( &settings->siblings );
+ INIT_LIST_HEAD ( &settings->children );
+ settings->op = op;
+ settings->refcnt = refcnt;
+ settings->name = name;
+}
+
+/**
+ * Initialise a settings block
+ *
+ * @v simple Simple settings block
+ * @v refcnt Containing object reference counter, or NULL
+ * @v name Settings block name
+ */
+static inline void simple_settings_init ( struct simple_settings *simple,
+ struct refcnt *refcnt,
+ const char *name ) {
+ settings_init ( &simple->settings, &simple_settings_operations,
+ refcnt, name );
+}
+
+/**
+ * Delete setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to delete
+ * @ret rc Return status code
+ */
+static inline int delete_setting ( struct settings *settings,
+ struct setting *setting ) {
+ return store_setting ( settings, setting, NULL, 0 );
+}
+
+/**
+ * Fetch and format value of setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v type Settings type
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+static inline int fetchf_setting ( struct settings *settings,
+ struct setting *setting,
+ char *buf, size_t len ) {
+ return setting->type->fetchf ( settings, setting, buf, len );
+}
+
+/**
+ * Delete named setting
+ *
+ * @v name Name of setting
+ * @ret rc Return status code
+ */
+static inline int delete_named_setting ( const char *name ) {
+ return storef_named_setting ( name, NULL );
+}
+
+#endif /* _GPXE_SETTINGS_H */
diff --git a/gpxe/src/include/gpxe/settings_ui.h b/gpxe/src/include/gpxe/settings_ui.h
new file mode 100644
index 00000000..48548fd5
--- /dev/null
+++ b/gpxe/src/include/gpxe/settings_ui.h
@@ -0,0 +1,14 @@
+#ifndef _GPXE_SETTINGS_UI_H
+#define _GPXE_SETTINGS_UI_H
+
+/** @file
+ *
+ * Option configuration console
+ *
+ */
+
+struct settings;
+
+extern int settings_ui ( struct settings *settings ) __nonnull;
+
+#endif /* _GPXE_SETTINGS_UI_H */
diff --git a/gpxe/src/include/gpxe/sha1.h b/gpxe/src/include/gpxe/sha1.h
new file mode 100644
index 00000000..2d6e90dd
--- /dev/null
+++ b/gpxe/src/include/gpxe/sha1.h
@@ -0,0 +1,13 @@
+#ifndef _GPXE_SHA1_H
+#define _GPXE_SHA1_H
+
+#include "crypto/axtls/crypto.h"
+
+struct crypto_algorithm;
+
+#define SHA1_CTX_SIZE sizeof ( SHA1_CTX )
+#define SHA1_DIGEST_SIZE SHA1_SIZE
+
+extern struct crypto_algorithm sha1_algorithm;
+
+#endif /* _GPXE_SHA1_H */
diff --git a/gpxe/src/include/gpxe/shell.h b/gpxe/src/include/gpxe/shell.h
new file mode 100644
index 00000000..c353fc4d
--- /dev/null
+++ b/gpxe/src/include/gpxe/shell.h
@@ -0,0 +1,12 @@
+#ifndef _GPXE_SHELL_H
+#define _GPXE_SHELL_H
+
+/** @file
+ *
+ * Minimal command shell
+ *
+ */
+
+extern void shell ( void );
+
+#endif /* _GPXE_SHELL_H */
diff --git a/gpxe/src/include/gpxe/shell_banner.h b/gpxe/src/include/gpxe/shell_banner.h
new file mode 100644
index 00000000..f8e92a4d
--- /dev/null
+++ b/gpxe/src/include/gpxe/shell_banner.h
@@ -0,0 +1,12 @@
+#ifndef _GPXE_SHELL_BANNER_H
+#define _GPXE_SHELL_BANNER_H
+
+/** @file
+ *
+ * Shell startup banner
+ *
+ */
+
+extern int shell_banner ( void );
+
+#endif /* _GPXE_SHELL_BANNER_H */
diff --git a/gpxe/src/include/gpxe/socket.h b/gpxe/src/include/gpxe/socket.h
new file mode 100644
index 00000000..9c7afb87
--- /dev/null
+++ b/gpxe/src/include/gpxe/socket.h
@@ -0,0 +1,95 @@
+#ifndef _GPXE_SOCKET_H
+#define _GPXE_SOCKET_H
+
+/** @file
+ *
+ * Socket addresses
+ *
+ */
+
+/**
+ * @defgroup commtypes Communication semantics
+ *
+ * @{
+ */
+
+/** Connection-based, reliable streams */
+#define SOCK_STREAM ( ( int ) TCP_SOCK_STREAM )
+extern char TCP_SOCK_STREAM[];
+
+/** Connectionless, unreliable streams */
+#define SOCK_DGRAM ( ( int ) UDP_SOCK_DGRAM )
+extern char UDP_SOCK_DGRAM[];
+
+/** @} */
+
+/**
+ * Name communication semantics
+ *
+ * @v semantics Communication semantics (e.g. SOCK_STREAM)
+ * @ret name Name of communication semantics
+ */
+static inline __attribute__ (( always_inline )) const char *
+socket_semantics_name ( int semantics ) {
+ /* Cannot use a switch() because of the {TCP_UDP}_SOCK_XXX hack */
+ if ( semantics == SOCK_STREAM ) {
+ return "SOCK_STREAM";
+ } else if ( semantics == SOCK_DGRAM ) {
+ return "SOCK_DGRAM";
+ } else {
+ return "SOCK_UNKNOWN";
+ }
+}
+
+/**
+ * @defgroup addrfam Address families
+ *
+ * @{
+ */
+#define AF_INET 1 /**< IPv4 Internet addresses */
+#define AF_INET6 2 /**< IPv6 Internet addresses */
+/** @} */
+
+/**
+ * Name address family
+ *
+ * @v family Address family (e.g. AF_INET)
+ * @ret name Name of address family
+ */
+static inline __attribute__ (( always_inline )) const char *
+socket_family_name ( int family ) {
+ switch ( family ) {
+ case AF_INET: return "AF_INET";
+ case AF_INET6: return "AF_INET6";
+ default: return "AF_UNKNOWN";
+ }
+}
+
+/** A socket address family */
+typedef uint16_t sa_family_t;
+
+/** Length of a @c struct @c sockaddr */
+#define SA_LEN 32
+
+/**
+ * Generalized socket address structure
+ *
+ * This contains the fields common to socket addresses for all address
+ * families.
+ */
+struct sockaddr {
+ /** Socket address family
+ *
+ * This is an AF_XXX constant.
+ */
+ sa_family_t sa_family;
+ /** Padding
+ *
+ * This ensures that a struct @c sockaddr_tcpip is large
+ * enough to hold a socket address for any TCP/IP address
+ * family.
+ */
+ char pad[ SA_LEN - sizeof ( sa_family_t ) ];
+};
+
+#endif /* _GPXE_SOCKET_H */
diff --git a/gpxe/src/include/gpxe/spi.h b/gpxe/src/include/gpxe/spi.h
new file mode 100644
index 00000000..fe38cb6b
--- /dev/null
+++ b/gpxe/src/include/gpxe/spi.h
@@ -0,0 +1,239 @@
+#ifndef _GPXE_SPI_H
+#define _GPXE_SPI_H
+
+/** @file
+ *
+ * SPI interface
+ *
+ */
+
+#include <gpxe/nvs.h>
+
+/**
+ * @defgroup spicmds SPI commands
+ * @{
+ */
+
+/** Write status register */
+#define SPI_WRSR 0x01
+
+/** Write data to memory array */
+#define SPI_WRITE 0x02
+
+/** Read data from memory array */
+#define SPI_READ 0x03
+
+/** Reset write enable latch */
+#define SPI_WRDI 0x04
+
+/** Read status register */
+#define SPI_RDSR 0x05
+
+/** Set write enable latch */
+#define SPI_WREN 0x06
+
+/**
+ * @defgroup atmelcmds Atmel-specific SPI commands
+ * @{
+ */
+
+/** Erase one sector in memory array (Not supported on all devices) */
+#define ATMEL_SECTOR_ERASE 0x52
+
+/** Erase all sections in memory array (Not supported on all devices) */
+#define ATMEL_CHIP_ERASE 0x62
+
+/** Read manufacturer and product ID (Not supported on all devices) */
+#define ATMEL_RDID 0x15
+
+/** @} */
+
+/** @} */
+
+/**
+ * @defgroup spistatus SPI status register bits (not present on all devices)
+ * @{
+ */
+
+/** Write-protect pin enabled */
+#define SPI_STATUS_WPEN 0x80
+
+/** Block protection bit 2 */
+#define SPI_STATUS_BP2 0x10
+
+/** Block protection bit 1 */
+#define SPI_STATUS_BP1 0x08
+
+/** Block protection bit 0 */
+#define SPI_STATUS_BP0 0x04
+
+/** State of the write enable latch */
+#define SPI_STATUS_WEN 0x02
+
+/** Device busy flag */
+#define SPI_STATUS_NRDY 0x01
+
+/** @} */
+
+/**
+ * An SPI device
+ *
+ * This data structure represents a physical SPI device attached to an
+ * SPI bus.
+ */
+struct spi_device {
+ /** NVS device */
+ struct nvs_device nvs;
+ /** SPI bus to which device is attached */
+ struct spi_bus *bus;
+ /** Slave number */
+ unsigned int slave;
+ /** Command length, in bits */
+ unsigned int command_len;
+ /** Address length, in bits */
+ unsigned int address_len;
+ /** Address is munged
+ *
+ * Some devices with 9-bit addresses (e.g. AT25040A EEPROM)
+ * use bit 3 of the command byte as address bit A8, rather
+ * than having a two-byte address. If this flag is set, then
+ * commands should be munged in this way.
+ */
+ unsigned int munge_address : 1;
+};
+
+static inline __attribute__ (( always_inline )) struct spi_device *
+nvs_to_spi ( struct nvs_device *nvs ) {
+ return container_of ( nvs, struct spi_device, nvs );
+}
+
+/**
+ * An SPI bus
+ *
+ * This data structure represents an SPI bus controller capable of
+ * issuing commands to attached SPI devices.
+ */
+struct spi_bus {
+ /** SPI interface mode
+ *
+ * This is the bitwise OR of zero or more of @c SPI_MODE_CPHA
+ * and @c SPI_MODE_CPOL. It is also the number conventionally
+ * used to describe the SPI interface mode. For example, SPI
+ * mode 1 is the mode in which CPOL=0 and CPHA=1, which
+ * therefore corresponds to a mode value of (0|SPI_MODE_CPHA)
+ * which, happily, equals 1.
+ */
+ unsigned int mode;
+ /**
+ * Read/write data via SPI bus
+ *
+ * @v bus SPI bus
+ * @v device SPI device
+ * @v command Command
+ * @v address Address to read/write (<0 for no address)
+ * @v data_out TX data buffer (or NULL)
+ * @v data_in RX data buffer (or NULL)
+ * @v len Length of data buffer(s)
+ *
+ * This issues the specified command and optional address to
+ * the SPI device, then reads and/or writes data to/from the
+ * data buffers.
+ */
+ int ( * rw ) ( struct spi_bus *bus, struct spi_device *device,
+ unsigned int command, int address,
+ const void *data_out, void *data_in, size_t len );
+};
+
+/** Clock phase (CPHA) mode bit
+ *
+ * Phase 0 is sample on rising edge, shift data on falling edge.
+ *
+ * Phase 1 is shift data on rising edge, sample data on falling edge.
+ */
+#define SPI_MODE_CPHA 0x01
+
+/** Clock polarity (CPOL) mode bit
+ *
+ * This bit reflects the idle state of the clock line (SCLK).
+ */
+#define SPI_MODE_CPOL 0x02
+
+/** Slave select polarity mode bit
+ *
+ * This bit reflects that active state of the slave select lines. It
+ * is not part of the normal SPI mode number (which covers only @c
+ * SPI_MODE_CPOL and @c SPI_MODE_CPHA), but is included here for
+ * convenience.
+ */
+#define SPI_MODE_SSPOL 0x10
+
+/** Microwire-compatible mode
+ *
+ * This is SPI mode 1 (i.e. CPOL=0, CPHA=1), and is compatible with
+ * the original Microwire protocol.
+ */
+#define SPI_MODE_MICROWIRE 1
+
+/** Microwire/Plus-compatible mode
+ *
+ * This is SPI mode 0 (i.e. CPOL=0, CPHA=0), and is compatible with
+ * the Microwire/Plus protocol
+ */
+#define SPI_MODE_MICROWIRE_PLUS 0
+
+/** Threewire-compatible mode
+ *
+ * This mode is compatible with Atmel's series of "three-wire"
+ * interfaces.
+ */
+#define SPI_MODE_THREEWIRE ( SPI_MODE_MICROWIRE_PLUS | SPI_MODE_SSPOL )
+
+extern int spi_read ( struct nvs_device *nvs, unsigned int address,
+ void *data, size_t len );
+extern int spi_write ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t len );
+
+/**
+ * @defgroup spidevs SPI device types
+ * @{
+ */
+
+static inline __attribute__ (( always_inline )) void
+init_spi ( struct spi_device *device ) {
+ device->nvs.word_len_log2 = 0;
+ device->command_len = 8,
+ device->nvs.read = spi_read;
+ device->nvs.write = spi_write;
+}
+
+/** Atmel AT25F1024 serial flash */
+static inline __attribute__ (( always_inline )) void
+init_at25f1024 ( struct spi_device *device ) {
+ device->address_len = 24;
+ device->nvs.size = ( 128 * 1024 );
+ device->nvs.block_size = 256;
+ init_spi ( device );
+}
+
+/** Atmel 25040 serial EEPROM */
+static inline __attribute__ (( always_inline )) void
+init_at25040 ( struct spi_device *device ) {
+ device->address_len = 8;
+ device->munge_address = 1;
+ device->nvs.size = 512;
+ device->nvs.block_size = 8;
+ init_spi ( device );
+}
+
+/** Microchip 25XX640 serial EEPROM */
+static inline __attribute__ (( always_inline )) void
+init_mc25xx640 ( struct spi_device *device ) {
+ device->address_len = 16;
+ device->nvs.size = ( 8 * 1024 );
+ device->nvs.block_size = 32;
+ init_spi ( device );
+}
+
+/** @} */
+
+#endif /* _GPXE_SPI_H */
diff --git a/gpxe/src/include/gpxe/spi_bit.h b/gpxe/src/include/gpxe/spi_bit.h
new file mode 100644
index 00000000..ced85ceb
--- /dev/null
+++ b/gpxe/src/include/gpxe/spi_bit.h
@@ -0,0 +1,61 @@
+#ifndef _GPXE_SPI_BIT_H
+#define _GPXE_SPI_BIT_H
+
+/** @file
+ *
+ * SPI bit-bashing interface
+ *
+ */
+
+#include <gpxe/spi.h>
+#include <gpxe/bitbash.h>
+
+/** A bit-bashing SPI bus */
+struct spi_bit_basher {
+ /** SPI bus */
+ struct spi_bus bus;
+ /** Bit-bashing interface */
+ struct bit_basher basher;
+ /** Endianness of data
+ *
+ * SPI commands and addresses are always big-endian (i.e. MSB
+ * transmitted first on the wire), but some cards
+ * (e.g. natsemi) choose to regard the data stored in the
+ * EEPROM as little-endian (i.e. LSB transmitted first on the
+ * wire).
+ */
+ int endianness;
+};
+
+/** Bit indices used for SPI bit-bashing interface */
+enum {
+ /** Serial clock */
+ SPI_BIT_SCLK = 0,
+ /** Master Out Slave In */
+ SPI_BIT_MOSI,
+ /** Master In Slave Out */
+ SPI_BIT_MISO,
+ /** Slave 0 select */
+ SPI_BIT_SS0,
+};
+
+/**
+ * Determine bit index for a particular slave
+ *
+ * @v slave Slave number
+ * @ret index Bit index (i.e. SPI_BIT_SSN, where N=slave)
+ */
+#define SPI_BIT_SS( slave ) ( SPI_BIT_SS0 + (slave) )
+
+/** Delay between SCLK transitions */
+#define SPI_BIT_UDELAY 1
+
+/** SPI bit basher treats data as big-endian */
+#define SPI_BIT_BIG_ENDIAN 0
+
+/** SPI bit basher treats data as little-endian */
+#define SPI_BIT_LITTLE_ENDIAN 1
+
+extern void init_spi_bit_basher ( struct spi_bit_basher *spibit );
+
+#endif /* _GPXE_SPI_BIT_H */
diff --git a/gpxe/src/include/gpxe/tables.h b/gpxe/src/include/gpxe/tables.h
new file mode 100644
index 00000000..b2c56ab6
--- /dev/null
+++ b/gpxe/src/include/gpxe/tables.h
@@ -0,0 +1,229 @@
+#ifndef _GPXE_TABLES_H
+#define _GPXE_TABLES_H
+
+/** @page ifdef_harmful #ifdef considered harmful
+ *
+ * Overuse of @c #ifdef has long been a problem in Etherboot.
+ * Etherboot provides a rich array of features, but all these features
+ * take up valuable space in a ROM image. The traditional solution to
+ * this problem has been for each feature to have its own @c #ifdef
+ * option, allowing the feature to be compiled in only if desired.
+ *
+ * The problem with this is that it becomes impossible to compile, let
+ * alone test, all possible versions of Etherboot. Code that is not
+ * typically used tends to suffer from bit-rot over time. It becomes
+ * extremely difficult to predict which combinations of compile-time
+ * options will result in code that can even compile and link
+ * correctly.
+ *
+ * To solve this problem, we have adopted a new approach from
+ * Etherboot 5.5 onwards. @c #ifdef is now "considered harmful", and
+ * its use should be minimised. Separate features should be
+ * implemented in separate @c .c files, and should \b always be
+ * compiled (i.e. they should \b not be guarded with a @c #ifdef @c
+ * MY_PET_FEATURE statement). By making (almost) all code always
+ * compile, we avoid the problem of bit-rot in rarely-used code.
+ *
+ * The file config.h, in combination with the @c make command line,
+ * specifies the objects that will be included in any particular build
+ * of Etherboot. For example, suppose that config.h includes the line
+ *
+ * @code
+ *
+ * #define CONSOLE_SERIAL
+ * #define DOWNLOAD_PROTO_TFTP
+ *
+ * @endcode
+ *
+ * When a particular Etherboot image (e.g. @c bin/rtl8139.zdsk) is
+ * built, the options specified in config.h are used to drag in the
+ * relevant objects at link-time. For the above example, serial.o and
+ * tftp.o would be linked in.
+ *
+ * There remains one problem to solve: how do these objects get used?
+ * Traditionally, we had code such as
+ *
+ * @code
+ *
+ * #ifdef CONSOLE_SERIAL
+ * serial_init();
+ * #endif
+ *
+ * @endcode
+ *
+ * in main.c, but this reintroduces @c #ifdef and so is a Bad Idea.
+ * We cannot simply remove the @c #ifdef and make it
+ *
+ * @code
+ *
+ * serial_init();
+ *
+ * @endcode
+ *
+ * because then serial.o would end up always being linked in.
+ *
+ * The solution is to use @link tables.h linker tables @endlink.
+ *
+ */
+
+/** @file
+ *
+ * Linker tables
+ *
+ * Read @ref ifdef_harmful first for some background on the motivation
+ * for using linker tables.
+ *
+ * This file provides macros for dealing with linker-generated tables
+ * of fixed-size symbols. We make fairly extensive use of these in
+ * order to avoid @c #ifdef spaghetti and/or linker symbol pollution.
+ * For example, instead of having code such as
+ *
+ * @code
+ *
+ * #ifdef CONSOLE_SERIAL
+ * serial_init();
+ * #endif
+ *
+ * @endcode
+ *
+ * we make serial.c generate an entry in the initialisation function
+ * table, and then have a function call_init_fns() that simply calls
+ * all functions present in this table. If and only if serial.o gets
+ * linked in, then its initialisation function will be called. We
+ * avoid linker symbol pollution (i.e. always dragging in serial.o
+ * just because of a call to serial_init()) and we also avoid @c
+ * #ifdef spaghetti (having to conditionalise every reference to
+ * functions in serial.c).
+ *
+ * The linker script takes care of assembling the tables for us. All
+ * our table sections have names of the format @c .tbl.NAME.NN where
+ * @c NAME designates the data structure stored in the table (e.g. @c
+ * init_fn) and @c NN is a two-digit decimal number used to impose an
+ * ordering upon the tables if required. @c NN=00 is reserved for the
+ * symbol indicating "table start", and @c NN=99 is reserved for the
+ * symbol indicating "table end".
+ *
+ * As an example, suppose that we want to create a "frobnicator"
+ * feature framework, and allow for several independent modules to
+ * provide frobnicating services. Then we would create a frob.h
+ * header file containing e.g.
+ *
+ * @code
+ *
+ * struct frobnicator {
+ * const char *name; // Name of the frobnicator
+ * void ( *frob ) ( void ); // The frobnicating function itself
+ * };
+ *
+ * #define __frobnicator __table ( frobnicators, 01 )
+ *
+ * @endcode
+ *
+ * Any module providing frobnicating services would look something
+ * like
+ *
+ * @code
+ *
+ * #include "frob.h"
+ *
+ * static void my_frob ( void ) {
+ * // Do my frobnicating
+ * ...
+ * }
+ *
+ * struct frob my_frobnicator __frobnicator = {
+ * .name = "my_frob",
+ * .frob = my_frob,
+ * };
+ *
+ * @endcode
+ *
+ * The central frobnicator code (frob.c) would use the frobnicating
+ * modules as follows
+ *
+ * @code
+ *
+ * #include "frob.h"
+ *
+ * static struct frob frob_start[0] __table_start ( frobnicators );
+ * static struct frob frob_end[0] __table_end ( frobnicators );
+ *
+ * // Call all linked-in frobnicators
+ * void frob_all ( void ) {
+ * struct frob *frob;
+ *
+ * for ( frob = frob_start ; frob < frob_end ; frob++ ) {
+ * printf ( "Calling frobnicator \"%s\"\n", frob->name );
+ * frob->frob ();
+ * }
+ * }
+ *
+ * @endcode
+ *
+ * See init.h and init.c for a real-life example.
+ *
+ */
+
+#ifdef DOXYGEN
+#define __attribute__( x )
+#endif
+
+#define __table_str( x ) #x
+#define __table_section( table, idx ) \
+ __section__ ( ".tbl." __table_str ( table ) "." __table_str ( idx ) )
+
+#define __table_section_start( table ) __table_section ( table, 00 )
+#define __table_section_end( table ) __table_section ( table, 99 )
+
+#define __natural_alignment( type ) __aligned__ ( __alignof__ ( type ) )
+
+/**
+ * Linker table entry.
+ *
+ * Declares a data structure to be part of a linker table. Use as
+ * e.g.
+ *
+ * @code
+ *
+ * struct my_foo __table ( foo, 01 ) = {
+ * ...
+ * };
+ *
+ * @endcode
+ *
+ */
+#define __table( type, table, idx ) \
+ __attribute__ (( __table_section ( table, idx ), \
+ __natural_alignment ( type ) ))
+
+/**
+ * Linker table start marker.
+ *
+ * Declares a data structure (usually an empty data structure) to be
+ * the start of a linker table. Use as e.g.
+ *
+ * @code
+ *
+ * static struct foo_start[0] __table_start ( foo );
+ *
+ * @endcode
+ *
+ */
+#define __table_start( type, table ) __table ( type, table, 00 )
+
+/**
+ * Linker table end marker.
+ *
+ * Declares a data structure (usually an empty data structure) to be
+ * the end of a linker table. Use as e.g.
+ *
+ * @code
+ *
+ * static struct foo_end[0] __table_end ( foo );
+ *
+ * @endcode
+ *
+ */
+#define __table_end( type, table ) __table ( type, table, 99 )
+
+#endif /* _GPXE_TABLES_H */
diff --git a/gpxe/src/include/gpxe/tcp.h b/gpxe/src/include/gpxe/tcp.h
new file mode 100644
index 00000000..264ec29b
--- /dev/null
+++ b/gpxe/src/include/gpxe/tcp.h
@@ -0,0 +1,306 @@
+#ifndef _GPXE_TCP_H
+#define _GPXE_TCP_H
+
+/** @file
+ *
+ * TCP protocol
+ *
+ * This file defines the gPXE TCP API.
+ *
+ */
+
+#include <gpxe/tcpip.h>
+
+/**
+ * A TCP header
+ */
+struct tcp_header {
+ uint16_t src; /* Source port */
+ uint16_t dest; /* Destination port */
+ uint32_t seq; /* Sequence number */
+ uint32_t ack; /* Acknowledgement number */
+ uint8_t hlen; /* Header length (4), Reserved (4) */
+ uint8_t flags; /* Reserved (2), Flags (6) */
+ uint16_t win; /* Advertised window */
+ uint16_t csum; /* Checksum */
+ uint16_t urg; /* Urgent pointer */
+};
+
+/** @defgroup tcpopts TCP options
+ * @{
+ */
+
+/** End of TCP options list */
+#define TCP_OPTION_END 0
+
+/** TCP option pad */
+#define TCP_OPTION_NOP 1
+
+/** Generic TCP option */
+struct tcp_option {
+ uint8_t kind;
+ uint8_t length;
+} __attribute__ (( packed ));
+
+/** TCP MSS option */
+struct tcp_mss_option {
+ uint8_t kind;
+ uint8_t length;
+ uint16_t mss;
+} __attribute__ (( packed ));
+
+/** Code for the TCP MSS option */
+#define TCP_OPTION_MSS 2
+
+/** TCP timestamp option */
+struct tcp_timestamp_option {
+ uint8_t kind;
+ uint8_t length;
+ uint32_t tsval;
+ uint32_t tsecr;
+} __attribute__ (( packed ));
+
+/** Padded TCP timestamp option (used for sending) */
+struct tcp_timestamp_padded_option {
+ uint8_t nop[2];
+ struct tcp_timestamp_option tsopt;
+} __attribute__ (( packed ));
+
+/** Code for the TCP timestamp option */
+#define TCP_OPTION_TS 8
+
+/** Parsed TCP options */
+struct tcp_options {
+ /** MSS option, if present */
+ const struct tcp_mss_option *mssopt;
+ /** Timestampe option, if present */
+ const struct tcp_timestamp_option *tsopt;
+};
+
+/** @} */
+
+/*
+ * TCP flags
+ */
+#define TCP_CWR 0x80
+#define TCP_ECE 0x40
+#define TCP_URG 0x20
+#define TCP_ACK 0x10
+#define TCP_PSH 0x08
+#define TCP_RST 0x04
+#define TCP_SYN 0x02
+#define TCP_FIN 0x01
+
+/**
+* @defgroup tcpstates TCP states
+*
+* The TCP state is defined by a combination of the flags that have
+* been sent to the peer, the flags that have been acknowledged by the
+* peer, and the flags that have been received from the peer.
+*
+* @{
+*/
+
+/** TCP flags that have been sent in outgoing packets */
+#define TCP_STATE_SENT(flags) ( (flags) << 0 )
+#define TCP_FLAGS_SENT(state) ( ( (state) >> 0 ) & 0xff )
+
+/** TCP flags that have been acknowledged by the peer
+ *
+ * Note that this applies only to SYN and FIN.
+ */
+#define TCP_STATE_ACKED(flags) ( (flags) << 8 )
+#define TCP_FLAGS_ACKED(state) ( ( (state) >> 8 ) & 0xff )
+
+/** TCP flags that have been received from the peer
+ *
+ * Note that this applies only to SYN and FIN, and that once SYN has
+ * been received, we should always be sending ACK.
+ */
+#define TCP_STATE_RCVD(flags) ( (flags) << 16 )
+#define TCP_FLAGS_RCVD(state) ( ( (state) >> 16 ) & 0xff )
+
+/** TCP flags that are currently being sent in outgoing packets */
+#define TCP_FLAGS_SENDING(state) \
+ ( TCP_FLAGS_SENT ( state ) & ~TCP_FLAGS_ACKED ( state ) )
+
+/** CLOSED
+ *
+ * The connection has not yet been used for anything.
+ */
+#define TCP_CLOSED TCP_RST
+
+/** LISTEN
+ *
+ * Not currently used as a state; we have no support for listening
+ * connections. Given a unique value to avoid compiler warnings.
+ */
+#define TCP_LISTEN 0
+
+/** SYN_SENT
+ *
+ * SYN has been sent, nothing has yet been received or acknowledged.
+ */
+#define TCP_SYN_SENT ( TCP_STATE_SENT ( TCP_SYN ) )
+
+/** SYN_RCVD
+ *
+ * SYN has been sent but not acknowledged, SYN has been received.
+ */
+#define TCP_SYN_RCVD ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK ) | \
+ TCP_STATE_RCVD ( TCP_SYN ) )
+
+/** ESTABLISHED
+ *
+ * SYN has been sent and acknowledged, SYN has been received.
+ */
+#define TCP_ESTABLISHED ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK ) | \
+ TCP_STATE_ACKED ( TCP_SYN ) | \
+ TCP_STATE_RCVD ( TCP_SYN ) )
+
+/** FIN_WAIT_1
+ *
+ * SYN has been sent and acknowledged, SYN has been received, FIN has
+ * been sent but not acknowledged, FIN has not been received.
+ *
+ * RFC 793 shows that we can enter FIN_WAIT_1 without have had SYN
+ * acknowledged, i.e. if the application closes the connection after
+ * sending and receiving SYN, but before having had SYN acknowledged.
+ * However, we have to *pretend* that SYN has been acknowledged
+ * anyway, otherwise we end up sending SYN and FIN in the same
+ * sequence number slot. Therefore, when we transition from SYN_RCVD
+ * to FIN_WAIT_1, we have to remember to set TCP_STATE_ACKED(TCP_SYN)
+ * and increment our sequence number.
+ */
+#define TCP_FIN_WAIT_1 ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK | TCP_FIN ) | \
+ TCP_STATE_ACKED ( TCP_SYN ) | \
+ TCP_STATE_RCVD ( TCP_SYN ) )
+
+/** FIN_WAIT_2
+ *
+ * SYN has been sent and acknowledged, SYN has been received, FIN has
+ * been sent and acknowledged, FIN ha not been received.
+ */
+#define TCP_FIN_WAIT_2 ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK | TCP_FIN ) | \
+ TCP_STATE_ACKED ( TCP_SYN | TCP_FIN ) | \
+ TCP_STATE_RCVD ( TCP_SYN ) )
+
+/** CLOSING / LAST_ACK
+ *
+ * SYN has been sent and acknowledged, SYN has been received, FIN has
+ * been sent but not acknowledged, FIN has been received.
+ *
+ * This state actually encompasses both CLOSING and LAST_ACK; they are
+ * identical with the definition of state that we use. I don't
+ * *believe* that they need to be distinguished.
+ */
+#define TCP_CLOSING_OR_LAST_ACK \
+ ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK | TCP_FIN ) | \
+ TCP_STATE_ACKED ( TCP_SYN ) | \
+ TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) )
+
+/** TIME_WAIT
+ *
+ * SYN has been sent and acknowledged, SYN has been received, FIN has
+ * been sent and acknowledged, FIN has been received.
+ */
+#define TCP_TIME_WAIT ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK | TCP_FIN ) | \
+ TCP_STATE_ACKED ( TCP_SYN | TCP_FIN ) | \
+ TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) )
+
+/** CLOSE_WAIT
+ *
+ * SYN has been sent and acknowledged, SYN has been received, FIN has
+ * been received.
+ */
+#define TCP_CLOSE_WAIT ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK ) | \
+ TCP_STATE_ACKED ( TCP_SYN ) | \
+ TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) )
+
+/** Can send data in current state
+ *
+ * We can send data if and only if we have had our SYN acked and we
+ * have not yet sent our FIN.
+ */
+#define TCP_CAN_SEND_DATA(state) \
+ ( ( (state) & ( TCP_STATE_ACKED ( TCP_SYN ) | \
+ TCP_STATE_SENT ( TCP_FIN ) ) ) \
+ == TCP_STATE_ACKED ( TCP_SYN ) )
+
+/** Have closed gracefully
+ *
+ * We have closed gracefully if we have both received a FIN and had
+ * our own FIN acked.
+ */
+#define TCP_CLOSED_GRACEFULLY(state) \
+ ( ( (state) & ( TCP_STATE_ACKED ( TCP_FIN ) | \
+ TCP_STATE_RCVD ( TCP_FIN ) ) ) \
+ == ( TCP_STATE_ACKED ( TCP_FIN ) | TCP_STATE_RCVD ( TCP_FIN ) ) )
+
+/** @} */
+
+/** Mask for TCP header length field */
+#define TCP_MASK_HLEN 0xf0
+
+/** Smallest port number on which a TCP connection can listen */
+#define TCP_MIN_PORT 1
+
+/* Some IOB constants */
+#define MAX_HDR_LEN 100
+#define MAX_IOB_LEN 1500
+#define MIN_IOB_LEN MAX_HDR_LEN + 100 /* To account for padding by LL */
+
+/**
+ * Maxmimum advertised TCP window size
+ *
+ * We estimate the TCP window size as the amount of free memory we
+ * have. This is not strictly accurate (since it ignores any space
+ * already allocated as RX buffers), but it will do for now.
+ *
+ * Since we don't store out-of-order received packets, the
+ * retransmission penalty is that the whole window contents must be
+ * resent. This suggests keeping the window size small, but bear in
+ * mind that the maximum bandwidth on any link is limited to
+ *
+ * max_bandwidth = ( tcp_window / round_trip_time )
+ *
+ * With a 48kB window, which probably accurately reflects our amount
+ * of free memory, and a WAN RTT of say 200ms, this gives a maximum
+ * bandwidth of 240kB/s. This is sufficiently close to realistic that
+ * we will need to be careful that our advertised window doesn't end
+ * up limiting WAN download speeds.
+ *
+ * Finally, since the window goes into a 16-bit field and we cannot
+ * actually use 65536, we use a window size of (65536-4) to ensure
+ * that payloads remain dword-aligned.
+ */
+//#define TCP_MAX_WINDOW_SIZE ( 65536 - 4 )
+#define TCP_MAX_WINDOW_SIZE 4096
+
+/**
+ * Path MTU
+ *
+ * We really ought to implement Path MTU discovery. Until we do,
+ * anything with a path MTU greater than this may fail.
+ */
+#define TCP_PATH_MTU 1460
+
+/**
+ * Advertised TCP MSS
+ *
+ * We currently hardcode this to a reasonable value and hope that the
+ * sender uses path MTU discovery. The alternative is breaking the
+ * abstraction layer so that we can find out the MTU from the IP layer
+ * (which would have to find out from the net device layer).
+ */
+#define TCP_MSS 1460
+
+/** TCP maximum segment lifetime
+ *
+ * Currently set to 2 minutes, as per RFC 793.
+ */
+#define TCP_MSL ( 2 * 60 * TICKS_PER_SEC )
+
+extern struct tcpip_protocol tcp_protocol;
+
+#endif /* _GPXE_TCP_H */
diff --git a/gpxe/src/include/gpxe/tcpip.h b/gpxe/src/include/gpxe/tcpip.h
new file mode 100644
index 00000000..c0fadd23
--- /dev/null
+++ b/gpxe/src/include/gpxe/tcpip.h
@@ -0,0 +1,118 @@
+#ifndef _GPXE_TCPIP_H
+#define _GPXE_TCPIP_H
+
+/** @file
+ *
+ * Transport-network layer interface
+ *
+ */
+
+#include <stdint.h>
+#include <gpxe/socket.h>
+#include <gpxe/in.h>
+#include <gpxe/tables.h>
+
+struct io_buffer;
+struct net_device;
+
+/** Empty checksum value
+ *
+ * This is the TCP/IP checksum over a zero-length block of data.
+ */
+#define TCPIP_EMPTY_CSUM 0xffff
+
+/**
+ * TCP/IP socket address
+ *
+ * This contains the fields common to socket addresses for all TCP/IP
+ * address families.
+ */
+struct sockaddr_tcpip {
+ /** Socket address family (part of struct @c sockaddr) */
+ sa_family_t st_family;
+ /** TCP/IP port */
+ uint16_t st_port;
+ /** Padding
+ *
+ * This ensures that a struct @c sockaddr_tcpip is large
+ * enough to hold a socket address for any TCP/IP address
+ * family.
+ */
+ char pad[ sizeof ( struct sockaddr ) -
+ ( sizeof ( sa_family_t ) + sizeof ( uint16_t ) ) ];
+};
+
+/**
+ * A transport-layer protocol of the TCP/IP stack (eg. UDP, TCP, etc)
+ */
+struct tcpip_protocol {
+ /** Protocol name */
+ const char *name;
+ /**
+ * Process received packet
+ *
+ * @v iobuf I/O buffer
+ * @v st_src Partially-filled source address
+ * @v st_dest Partially-filled destination address
+ * @v pshdr_csum Pseudo-header checksum
+ * @ret rc Return status code
+ *
+ * This method takes ownership of the I/O buffer.
+ */
+ int ( * rx ) ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum );
+ /**
+ * Transport-layer protocol number
+ *
+ * This is a constant of the type IP_XXX
+ */
+ uint8_t tcpip_proto;
+};
+
+/**
+ * A network-layer protocol of the TCP/IP stack (eg. IPV4, IPv6, etc)
+ */
+struct tcpip_net_protocol {
+ /** Protocol name */
+ const char *name;
+ /** Network address family */
+ sa_family_t sa_family;
+ /**
+ * Transmit packet
+ *
+ * @v iobuf I/O buffer
+ * @v tcpip_protocol Transport-layer protocol
+ * @v st_dest Destination address
+ * @v netdev Network device (or NULL to route automatically)
+ * @v trans_csum Transport-layer checksum to complete, or NULL
+ * @ret rc Return status code
+ *
+ * This function takes ownership of the I/O buffer.
+ */
+ int ( * tx ) ( struct io_buffer *iobuf,
+ struct tcpip_protocol *tcpip_protocol,
+ struct sockaddr_tcpip *st_dest,
+ struct net_device *netdev,
+ uint16_t *trans_csum );
+};
+
+/** Declare a TCP/IP transport-layer protocol */
+#define __tcpip_protocol \
+ __table ( struct tcpip_protocol, tcpip_protocols, 01 )
+
+/** Declare a TCP/IP network-layer protocol */
+#define __tcpip_net_protocol \
+ __table ( struct tcpip_net_protocol, tcpip_net_protocols, 01 )
+
+extern int tcpip_rx ( struct io_buffer *iobuf, uint8_t tcpip_proto,
+ struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum );
+extern int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip,
+ struct sockaddr_tcpip *st_dest,
+ struct net_device *netdev,
+ uint16_t *trans_csum );
+extern uint16_t tcpip_continue_chksum ( uint16_t partial,
+ const void *data, size_t len );
+extern uint16_t tcpip_chksum ( const void *data, size_t len );
+
+#endif /* _GPXE_TCPIP_H */
diff --git a/gpxe/src/include/gpxe/tftp.h b/gpxe/src/include/gpxe/tftp.h
new file mode 100644
index 00000000..0177a95a
--- /dev/null
+++ b/gpxe/src/include/gpxe/tftp.h
@@ -0,0 +1,83 @@
+#ifndef _GPXE_TFTP_H
+#define _GPXE_TFTP_H
+
+/** @file
+ *
+ * TFTP protocol
+ *
+ */
+
+#include <stdint.h>
+
+#define TFTP_PORT 69 /**< Default TFTP server port */
+#define TFTP_DEFAULT_BLKSIZE 512 /**< Default TFTP data block size */
+#define TFTP_MAX_BLKSIZE 1432
+
+#define TFTP_RRQ 1 /**< Read request opcode */
+#define TFTP_WRQ 2 /**< Write request opcode */
+#define TFTP_DATA 3 /**< Data block opcode */
+#define TFTP_ACK 4 /**< Data block acknowledgement opcode */
+#define TFTP_ERROR 5 /**< Error opcode */
+#define TFTP_OACK 6 /**< Options acknowledgement opcode */
+
+#define TFTP_ERR_FILE_NOT_FOUND 1 /**< File not found */
+#define TFTP_ERR_ACCESS_DENIED 2 /**< Access violation */
+#define TFTP_ERR_DISK_FULL 3 /**< Disk full or allocation exceeded */
+#define TFTP_ERR_ILLEGAL_OP 4 /**< Illegal TFTP operation */
+#define TFTP_ERR_UNKNOWN_TID 5 /**< Unknown transfer ID */
+#define TFTP_ERR_FILE_EXISTS 6 /**< File already exists */
+#define TFTP_ERR_UNKNOWN_USER 7 /**< No such user */
+#define TFTP_ERR_BAD_OPTS 8 /**< Option negotiation failed */
+
+#define MTFTP_PORT 1759 /**< Default MTFTP server port */
+
+/** A TFTP read request (RRQ) packet */
+struct tftp_rrq {
+ uint16_t opcode;
+ char data[0];
+} __attribute__ (( packed ));
+
+/** A TFTP data (DATA) packet */
+struct tftp_data {
+ uint16_t opcode;
+ uint16_t block;
+ uint8_t data[0];
+} __attribute__ (( packed ));
+
+/** A TFTP acknowledgement (ACK) packet */
+struct tftp_ack {
+ uint16_t opcode;
+ uint16_t block;
+} __attribute__ (( packed ));
+
+/** A TFTP error (ERROR) packet */
+struct tftp_error {
+ uint16_t opcode;
+ uint16_t errcode;
+ char errmsg[0];
+} __attribute__ (( packed ));
+
+/** A TFTP options acknowledgement (OACK) packet */
+struct tftp_oack {
+ uint16_t opcode;
+ char data[0];
+} __attribute__ (( packed ));
+
+/** The common header of all TFTP packets */
+struct tftp_common {
+ uint16_t opcode;
+} __attribute__ (( packed ));
+
+/** A union encapsulating all TFTP packet types */
+union tftp_any {
+ struct tftp_common common;
+ struct tftp_rrq rrq;
+ struct tftp_data data;
+ struct tftp_ack ack;
+ struct tftp_error error;
+ struct tftp_oack oack;
+};
+
+extern void tftp_set_request_blksize ( unsigned int blksize );
+
+#endif /* _GPXE_TFTP_H */
diff --git a/gpxe/src/include/gpxe/threewire.h b/gpxe/src/include/gpxe/threewire.h
new file mode 100644
index 00000000..865fc25d
--- /dev/null
+++ b/gpxe/src/include/gpxe/threewire.h
@@ -0,0 +1,89 @@
+#ifndef _GPXE_THREEWIRE_H
+#define _GPXE_THREEWIRE_H
+
+/** @file
+ *
+ * Three-wire serial interface
+ *
+ * The Atmel three-wire interface is a subset of the (newer) SPI
+ * interface, and is implemented here as a layer on top of the SPI
+ * support.
+ */
+
+#include <gpxe/spi.h>
+#include <limits.h>
+
+/**
+ * @defgroup tcmds Three-wire commands
+ * @{
+ */
+
+/** Read data from memory array */
+#define THREEWIRE_READ 0x6
+
+/** Write data to memory array */
+#define THREEWIRE_WRITE 0x5
+
+/** Write enable */
+#define THREEWIRE_EWEN 0x4
+
+/** Address to be used for write enable command */
+#define THREEWIRE_EWEN_ADDRESS INT_MAX
+
+/** Time to wait for write cycles to complete
+ *
+ * This is sufficient for AT93C46/AT93C56 devices, but may need to be
+ * increased in future when other devices are added.
+ */
+#define THREEWIRE_WRITE_MDELAY 10
+
+/** @} */
+
+extern int threewire_read ( struct nvs_device *nvs, unsigned int address,
+ void *data, size_t len );
+extern int threewire_write ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t len );
+
+/**
+ * @defgroup tdevs Three-wire device types
+ * @{
+ */
+
+static inline __attribute__ (( always_inline )) void
+init_at93cx6 ( struct spi_device *device, unsigned int organisation ) {
+ device->nvs.word_len_log2 = ( ( organisation == 8 ) ? 0 : 1 );
+ device->nvs.block_size = 1;
+ device->command_len = 3,
+ device->nvs.read = threewire_read;
+ device->nvs.write = threewire_write;
+}
+
+/**
+ * Initialise Atmel AT93C46 serial EEPROM
+ *
+ * @v device SPI device
+ * @v organisation Word organisation (8 or 16)
+ */
+static inline __attribute__ (( always_inline )) void
+init_at93c46 ( struct spi_device *device, unsigned int organisation ) {
+ device->nvs.size = ( 1024 / organisation );
+ device->address_len = ( ( organisation == 8 ) ? 7 : 6 );
+ init_at93cx6 ( device, organisation );
+}
+
+/**
+ * Initialise Atmel AT93C56 serial EEPROM
+ *
+ * @v device SPI device
+ * @v organisation Word organisation (8 or 16)
+ */
+static inline __attribute__ (( always_inline )) void
+init_at93c56 ( struct spi_device *device, unsigned int organisation ) {
+ device->nvs.size = ( 2048 / organisation );
+ device->address_len = ( ( organisation == 8 ) ? 9 : 8 );
+ init_at93cx6 ( device, organisation );
+}
+
+/** @} */
+
+#endif /* _GPXE_THREEWIRE_H */
diff --git a/gpxe/src/include/gpxe/timer.h b/gpxe/src/include/gpxe/timer.h
new file mode 100644
index 00000000..b7057225
--- /dev/null
+++ b/gpxe/src/include/gpxe/timer.h
@@ -0,0 +1,41 @@
+#ifndef GPXE_TIMER_H
+#define GPXE_TIMER_H
+
+#include <stddef.h>
+#include <gpxe/tables.h>
+
+typedef unsigned long tick_t;
+
+#define MSECS_IN_SEC (1000)
+#define USECS_IN_SEC (1000*1000)
+#define USECS_IN_MSEC (1000)
+
+#define TICKS_PER_SEC USECS_IN_SEC
+
+extern tick_t currticks ( void );
+
+extern void generic_currticks_udelay ( unsigned int usecs );
+
+/** A timer */
+struct timer {
+ /** Initialise timer
+ *
+ * @ret rc Return status code
+ */
+ int ( * init ) ( void );
+ /** Read current time
+ *
+ * @ret ticks Current time, in ticks
+ */
+ tick_t ( * currticks ) ( void );
+ /** Delay
+ *
+ * @v usecs Time to delay, in microseconds
+ */
+ void ( * udelay ) ( unsigned int usecs );
+};
+
+#define __timer( order ) __table ( struct timer, timers, order )
+
+#endif /* GPXE_TIMER_H */
+
diff --git a/gpxe/src/include/gpxe/tls.h b/gpxe/src/include/gpxe/tls.h
new file mode 100644
index 00000000..a8cf16ef
--- /dev/null
+++ b/gpxe/src/include/gpxe/tls.h
@@ -0,0 +1,171 @@
+#ifndef _GPXE_TLS_H
+#define _GPXE_TLS_H
+
+/**
+ * @file
+ *
+ * Transport Layer Security Protocol
+ */
+
+#include <stdint.h>
+#include <gpxe/refcnt.h>
+#include <gpxe/filter.h>
+#include <gpxe/process.h>
+#include <gpxe/crypto.h>
+#include <gpxe/md5.h>
+#include <gpxe/sha1.h>
+
+/** A TLS header */
+struct tls_header {
+ /** Content type
+ *
+ * This is a TLS_TYPE_XXX constant
+ */
+ uint8_t type;
+ /** Protocol version
+ *
+ * This is a TLS_VERSION_XXX constant
+ */
+ uint16_t version;
+ /** Length of payload */
+ uint16_t length;
+} __attribute__ (( packed ));
+
+/** TLS version 1.0 */
+#define TLS_VERSION_TLS_1_0 0x0301
+
+/** TLS version 1.1 */
+#define TLS_VERSION_TLS_1_1 0x0302
+
+/** Change cipher content type */
+#define TLS_TYPE_CHANGE_CIPHER 20
+
+/** Alert content type */
+#define TLS_TYPE_ALERT 21
+
+/** Handshake content type */
+#define TLS_TYPE_HANDSHAKE 22
+
+/** Application data content type */
+#define TLS_TYPE_DATA 23
+
+/* Handshake message types */
+#define TLS_HELLO_REQUEST 0
+#define TLS_CLIENT_HELLO 1
+#define TLS_SERVER_HELLO 2
+#define TLS_CERTIFICATE 11
+#define TLS_SERVER_KEY_EXCHANGE 12
+#define TLS_CERTIFICATE_REQUEST 13
+#define TLS_SERVER_HELLO_DONE 14
+#define TLS_CERTIFICATE_VERIFY 15
+#define TLS_CLIENT_KEY_EXCHANGE 16
+#define TLS_FINISHED 20
+
+/* TLS alert levels */
+#define TLS_ALERT_WARNING 1
+#define TLS_ALERT_FATAL 2
+
+/* TLS cipher specifications */
+#define TLS_RSA_WITH_NULL_MD5 0x0001
+#define TLS_RSA_WITH_NULL_SHA 0x0002
+#define TLS_RSA_WITH_AES_128_CBC_SHA 0x002f
+#define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035
+
+/** TLS RX state machine state */
+enum tls_rx_state {
+ TLS_RX_HEADER = 0,
+ TLS_RX_DATA,
+};
+
+/** TLS TX state machine state */
+enum tls_tx_state {
+ TLS_TX_NONE = 0,
+ TLS_TX_CLIENT_HELLO,
+ TLS_TX_CLIENT_KEY_EXCHANGE,
+ TLS_TX_CHANGE_CIPHER,
+ TLS_TX_FINISHED,
+ TLS_TX_DATA
+};
+
+/** A TLS cipher specification */
+struct tls_cipherspec {
+ /** Public-key encryption algorithm */
+ struct crypto_algorithm *pubkey;
+ /** Bulk encryption cipher algorithm */
+ struct crypto_algorithm *cipher;
+ /** MAC digest algorithm */
+ struct crypto_algorithm *digest;
+ /** Key length */
+ size_t key_len;
+ /** Dynamically-allocated storage */
+ void *dynamic;
+ /** Public key encryption context */
+ void *pubkey_ctx;
+ /** Bulk encryption cipher context */
+ void *cipher_ctx;
+ /** Next bulk encryption cipher context (TX only) */
+ void *cipher_next_ctx;
+ /** MAC secret */
+ void *mac_secret;
+};
+
+/** A TLS session */
+struct tls_session {
+ /** Reference counter */
+ struct refcnt refcnt;
+
+ /** Plaintext stream */
+ struct xfer_filter_half plainstream;
+ /** Ciphertext stream */
+ struct xfer_filter_half cipherstream;
+
+ /** Current TX cipher specification */
+ struct tls_cipherspec tx_cipherspec;
+ /** Next TX cipher specification */
+ struct tls_cipherspec tx_cipherspec_pending;
+ /** Current RX cipher specification */
+ struct tls_cipherspec rx_cipherspec;
+ /** Next RX cipher specification */
+ struct tls_cipherspec rx_cipherspec_pending;
+ /** Premaster secret */
+ uint8_t pre_master_secret[48];
+ /** Master secret */
+ uint8_t master_secret[48];
+ /** Server random bytes */
+ uint8_t server_random[32];
+ /** Client random bytes */
+ uint8_t client_random[32];
+ /** MD5 context for handshake verification */
+ uint8_t handshake_md5_ctx[MD5_CTX_SIZE];
+ /** SHA1 context for handshake verification */
+ uint8_t handshake_sha1_ctx[SHA1_CTX_SIZE];
+
+ /** Hack: server RSA public key */
+ uint8_t *rsa_mod;
+ size_t rsa_mod_len;
+ uint8_t *rsa_pub_exp;
+ size_t rsa_pub_exp_len;
+
+ /** TX sequence number */
+ uint64_t tx_seq;
+ /** TX state */
+ enum tls_tx_state tx_state;
+ /** TX process */
+ struct process process;
+
+ /** RX sequence number */
+ uint64_t rx_seq;
+ /** RX state */
+ enum tls_rx_state rx_state;
+ /** Offset within current RX state */
+ size_t rx_rcvd;
+ /** Current received record header */
+ struct tls_header rx_header;
+ /** Current received raw data buffer */
+ void *rx_data;
+};
+
+extern int add_tls ( struct xfer_interface *xfer,
+ struct xfer_interface **next );
+
+#endif /* _GPXE_TLS_H */
diff --git a/gpxe/src/include/gpxe/uaccess.h b/gpxe/src/include/gpxe/uaccess.h
new file mode 100644
index 00000000..05f89e03
--- /dev/null
+++ b/gpxe/src/include/gpxe/uaccess.h
@@ -0,0 +1,27 @@
+#ifndef _GPXE_UACCESS_H
+#define _GPXE_UACCESS_H
+
+/**
+ * @file
+ *
+ * Access to external ("user") memory
+ *
+ * gPXE often needs to transfer data between internal and external
+ * buffers. On i386, the external buffers may require access via a
+ * different segment, and the buffer address cannot be encoded into a
+ * simple void * pointer. The @c userptr_t type encapsulates the
+ * information needed to identify an external buffer, and the
+ * copy_to_user() and copy_from_user() functions provide methods for
+ * transferring data between internal and external buffers.
+ *
+ * Note that userptr_t is an opaque type; in particular, performing
+ * arithmetic upon a userptr_t is not allowed.
+ *
+ */
+
+#include <bits/uaccess.h>
+
+/** Equivalent of NULL for user pointers */
+#define UNULL ( ( userptr_t ) 0 )
+
+#endif /* _GPXE_UACCESS_H */
diff --git a/gpxe/src/include/gpxe/udp.h b/gpxe/src/include/gpxe/udp.h
new file mode 100644
index 00000000..cb0e44eb
--- /dev/null
+++ b/gpxe/src/include/gpxe/udp.h
@@ -0,0 +1,47 @@
+#ifndef _GPXE_UDP_H
+#define _GPXE_UDP_H
+
+/** @file
+ *
+ * UDP protocol
+ *
+ * This file defines the gPXE UDP API.
+ *
+ */
+
+#include <stddef.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/tcpip.h>
+#include <gpxe/if_ether.h>
+
+struct xfer_interface;
+struct sockaddr;
+
+/**
+ * UDP constants
+ */
+
+#define UDP_MAX_HLEN 72
+#define UDP_MAX_TXIOB ETH_MAX_MTU
+#define UDP_MIN_TXIOB ETH_ZLEN
+
+/**
+ * A UDP header
+ */
+struct udp_header {
+ /** Source port */
+ uint16_t src;
+ /** Destination port */
+ uint16_t dest;
+ /** Length */
+ uint16_t len;
+ /** Checksum */
+ uint16_t chksum;
+};
+
+extern int udp_open_promisc ( struct xfer_interface *xfer );
+extern int udp_open ( struct xfer_interface *xfer, struct sockaddr *peer,
+ struct sockaddr *local );
+
+#endif /* _GPXE_UDP_H */
+
diff --git a/gpxe/src/include/gpxe/umalloc.h b/gpxe/src/include/gpxe/umalloc.h
new file mode 100644
index 00000000..49ec22b4
--- /dev/null
+++ b/gpxe/src/include/gpxe/umalloc.h
@@ -0,0 +1,17 @@
+#ifndef _GPXE_UMALLOC_H
+#define _GPXE_UMALLOC_H
+
+/**
+ * @file
+ *
+ * User memory allocation
+ *
+ */
+
+#include <gpxe/uaccess.h>
+
+extern userptr_t umalloc ( size_t size );
+extern userptr_t urealloc ( userptr_t ptr, size_t new_size );
+extern void ufree ( userptr_t ptr );
+
+#endif /* _GPXE_UMALLOC_H */
diff --git a/gpxe/src/include/gpxe/uri.h b/gpxe/src/include/gpxe/uri.h
new file mode 100644
index 00000000..514bc479
--- /dev/null
+++ b/gpxe/src/include/gpxe/uri.h
@@ -0,0 +1,139 @@
+#ifndef _GPXE_URI_H
+#define _GPXE_URI_H
+
+/** @file
+ *
+ * Uniform Resource Identifiers
+ *
+ */
+
+#include <stdlib.h>
+#include <gpxe/refcnt.h>
+
+/** A Uniform Resource Identifier
+ *
+ * Terminology for this data structure is as per uri(7), except that
+ * "path" is defined to include the leading '/' for an absolute path.
+ *
+ * Note that all fields within a URI are optional and may be NULL.
+ *
+ * Some examples are probably helpful:
+ *
+ * http://www.etherboot.org/wiki :
+ *
+ * scheme = "http", host = "www.etherboot.org", path = "/wiki"
+ *
+ * /var/lib/tftpboot :
+ *
+ * path = "/var/lib/tftpboot"
+ *
+ * mailto:bob@nowhere.com :
+ *
+ * scheme = "mailto", opaque = "bob@nowhere.com"
+ *
+ * ftp://joe:secret@insecure.org:8081/hidden/path/to?what=is#this
+ *
+ * scheme = "ftp", user = "joe", password = "secret",
+ * host = "insecure.org", port = "8081", path = "/hidden/path/to",
+ * query = "what=is", fragment = "this"
+ */
+struct uri {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Scheme */
+ const char *scheme;
+ /** Opaque part */
+ const char *opaque;
+ /** User name */
+ const char *user;
+ /** Password */
+ const char *password;
+ /** Host name */
+ const char *host;
+ /** Port number */
+ const char *port;
+ /** Path */
+ const char *path;
+ /** Query */
+ const char *query;
+ /** Fragment */
+ const char *fragment;
+};
+
+/**
+ * URI is an absolute URI
+ *
+ * @v uri URI
+ * @ret is_absolute URI is absolute
+ *
+ * An absolute URI begins with a scheme, e.g. "http:" or "mailto:".
+ * Note that this is a separate concept from a URI with an absolute
+ * path.
+ */
+static inline int uri_is_absolute ( struct uri *uri ) {
+ return ( uri->scheme != NULL );
+}
+
+/**
+ * URI has an absolute path
+ *
+ * @v uri URI
+ * @ret has_absolute_path URI has an absolute path
+ *
+ * An absolute path begins with a '/'. Note that this is a separate
+ * concept from an absolute URI. Note also that a URI may not have a
+ * path at all.
+ */
+static inline int uri_has_absolute_path ( struct uri *uri ) {
+ return ( uri->path && ( uri->path[0] == '/' ) );
+}
+
+/**
+ * URI has a relative path
+ *
+ * @v uri URI
+ * @ret has_relative_path URI has a relative path
+ *
+ * A relative path begins with something other than a '/'. Note that
+ * this is a separate concept from a relative URI. Note also that a
+ * URI may not have a path at all.
+ */
+static inline int uri_has_relative_path ( struct uri *uri ) {
+ return ( uri->path && ( uri->path[0] != '/' ) );
+}
+
+/**
+ * Increment URI reference count
+ *
+ * @v uri URI, or NULL
+ * @ret uri URI as passed in
+ */
+static inline __attribute__ (( always_inline )) struct uri *
+uri_get ( struct uri *uri ) {
+ ref_get ( &uri->refcnt );
+ return uri;
+}
+
+/**
+ * Decrement URI reference count
+ *
+ * @v uri URI, or NULL
+ */
+static inline __attribute__ (( always_inline )) void
+uri_put ( struct uri *uri ) {
+ ref_put ( &uri->refcnt );
+}
+
+extern struct uri *cwuri;
+
+extern struct uri * parse_uri ( const char *uri_string );
+extern unsigned int uri_port ( struct uri *uri, unsigned int default_port );
+extern int unparse_uri ( char *buf, size_t size, struct uri *uri );
+extern struct uri * uri_dup ( struct uri *uri );
+extern char * resolve_path ( const char *base_path,
+ const char *relative_path );
+extern struct uri * resolve_uri ( struct uri *base_uri,
+ struct uri *relative_uri );
+extern void churi ( struct uri *uri );
+
+#endif /* _GPXE_URI_H */
diff --git a/gpxe/src/include/gpxe/uuid.h b/gpxe/src/include/gpxe/uuid.h
new file mode 100644
index 00000000..a62735c9
--- /dev/null
+++ b/gpxe/src/include/gpxe/uuid.h
@@ -0,0 +1,34 @@
+#ifndef _GPXE_UUID_H
+#define _GPXE_UUID_H
+
+/** @file
+ *
+ * Universally unique IDs
+ */
+
+#include <stdint.h>
+
+union uuid;
+#include <bits/uuid.h>
+
+/** A universally unique ID */
+union uuid {
+ /** Canonical form (00000000-0000-0000-0000-000000000000) */
+ struct {
+ /** 8 hex digits, little-endian */
+ uint32_t a;
+ /** 2 hex digits, little-endian */
+ uint16_t b;
+ /** 2 hex digits, little-endian */
+ uint16_t c;
+ /** 2 hex digits, big-endian */
+ uint16_t d;
+ /** 12 hex digits, big-endian */
+ uint8_t e[6];
+ } canonical;
+ uint8_t raw[16];
+};
+
+extern char * uuid_ntoa ( union uuid *uuid );
+
+#endif /* _GPXE_UUID_H */
diff --git a/gpxe/src/include/gpxe/vsprintf.h b/gpxe/src/include/gpxe/vsprintf.h
new file mode 100644
index 00000000..9360f29b
--- /dev/null
+++ b/gpxe/src/include/gpxe/vsprintf.h
@@ -0,0 +1,71 @@
+#ifndef _GPXE_VSPRINTF_H
+#define _GPXE_VSPRINTF_H
+
+/** @file
+ *
+ * printf() and friends
+ *
+ * Etherboot's printf() functions understand the following subset of
+ * the standard C printf()'s format specifiers:
+ *
+ * - Flag characters
+ * - '#' - Alternate form (i.e. "0x" prefix)
+ * - '0' - Zero-pad
+ * - Field widths
+ * - Length modifiers
+ * - 'hh' - Signed / unsigned char
+ * - 'h' - Signed / unsigned short
+ * - 'l' - Signed / unsigned long
+ * - 'll' - Signed / unsigned long long
+ * - 'z' - Signed / unsigned size_t
+ * - Conversion specifiers
+ * - 'd' - Signed decimal
+ * - 'x','X' - Unsigned hexadecimal
+ * - 'c' - Character
+ * - 's' - String
+ * - 'p' - Pointer
+ *
+ * Hexadecimal numbers are always zero-padded to the specified field
+ * width (if any); decimal numbers are always space-padded. Decimal
+ * long longs are not supported.
+ *
+ */
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+/**
+ * A printf context
+ *
+ * Contexts are used in order to be able to share code between
+ * vprintf() and vsnprintf(), without requiring the allocation of a
+ * buffer for vprintf().
+ */
+struct printf_context {
+ /**
+ * Character handler
+ *
+ * @v ctx Context
+ * @v c Character
+ *
+ * This method is called for each character written to the
+ * formatted string.
+ */
+ void ( * handler ) ( struct printf_context *ctx, unsigned int c );
+ /** Length of formatted string
+ *
+ * When handler() is called, @len will be set to the number of
+ * characters written so far (i.e. zero for the first call to
+ * handler()).
+ */
+ size_t len;
+};
+
+extern size_t vcprintf ( struct printf_context *ctx, const char *fmt,
+ va_list args );
+extern int vssnprintf ( char *buf, ssize_t ssize, const char *fmt,
+ va_list args );
+extern int ssnprintf ( char *buf, ssize_t ssize, const char *fmt, ... );
+
+#endif /* _GPXE_VSPRINTF_H */
diff --git a/gpxe/src/include/gpxe/xfer.h b/gpxe/src/include/gpxe/xfer.h
new file mode 100644
index 00000000..9575bf69
--- /dev/null
+++ b/gpxe/src/include/gpxe/xfer.h
@@ -0,0 +1,275 @@
+#ifndef _GPXE_XFER_H
+#define _GPXE_XFER_H
+
+/** @file
+ *
+ * Data transfer interfaces
+ *
+ */
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <gpxe/interface.h>
+#include <gpxe/iobuf.h>
+
+struct xfer_interface;
+struct xfer_metadata;
+
+/** Data transfer interface operations */
+struct xfer_interface_operations {
+ /** Close interface
+ *
+ * @v xfer Data transfer interface
+ * @v rc Reason for close
+ */
+ void ( * close ) ( struct xfer_interface *xfer, int rc );
+ /** Redirect to new location
+ *
+ * @v xfer Data transfer interface
+ * @v type New location type
+ * @v args Remaining arguments depend upon location type
+ * @ret rc Return status code
+ */
+ int ( * vredirect ) ( struct xfer_interface *xfer, int type,
+ va_list args );
+ /** Check flow control window
+ *
+ * @v xfer Data transfer interface
+ * @ret len Length of window
+ *
+ * Flow control is regarded as advisory but not mandatory.
+ * Users who have control over their own rate of data
+ * generation should perform a flow control check before
+ * generating new data. Users who have no control (such as
+ * NIC drivers or filter layers) are not obliged to check.
+ *
+ * Data transfer interfaces must be prepared to accept
+ * datagrams even if they are advertising a window of zero
+ * bytes.
+ */
+ size_t ( * window ) ( struct xfer_interface *xfer );
+ /** Allocate I/O buffer
+ *
+ * @v xfer Data transfer interface
+ * @v len I/O buffer payload length
+ * @ret iobuf I/O buffer
+ */
+ struct io_buffer * ( * alloc_iob ) ( struct xfer_interface *xfer,
+ size_t len );
+ /** Deliver datagram as I/O buffer with metadata
+ *
+ * @v xfer Data transfer interface
+ * @v iobuf Datagram I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ *
+ * A data transfer interface that wishes to support only raw
+ * data delivery should set this method to
+ * xfer_deliver_as_raw().
+ */
+ int ( * deliver_iob ) ( struct xfer_interface *xfer,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta );
+ /** Deliver datagram as raw data
+ *
+ * @v xfer Data transfer interface
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ *
+ * A data transfer interface that wishes to support only I/O
+ * buffer delivery should set this method to
+ * xfer_deliver_as_iob().
+ */
+ int ( * deliver_raw ) ( struct xfer_interface *xfer,
+ const void *data, size_t len );
+};
+
+/** A data transfer interface */
+struct xfer_interface {
+ /** Generic object communication interface */
+ struct interface intf;
+ /** Operations for received messages */
+ struct xfer_interface_operations *op;
+};
+
+/** Basis positions for seek() events */
+enum seek_whence {
+ SEEK_CUR = 0,
+ SEEK_SET,
+};
+
+/** Data transfer metadata */
+struct xfer_metadata {
+ /** Position of data within stream */
+ off_t offset;
+ /** Basis for data position
+ *
+ * Must be one of @c SEEK_CUR or @c SEEK_SET.
+ */
+ int whence;
+ /** Source socket address, or NULL */
+ struct sockaddr *src;
+ /** Destination socket address, or NULL */
+ struct sockaddr *dest;
+ /** Network device, or NULL */
+ struct net_device *netdev;
+};
+
+/**
+ * Describe seek basis
+ *
+ * @v whence Basis for new position
+ */
+static inline __attribute__ (( always_inline )) const char *
+whence_text ( int whence ) {
+ switch ( whence ) {
+ case SEEK_CUR: return "CUR";
+ case SEEK_SET: return "SET";
+ default: return "INVALID";
+ }
+}
+
+extern struct xfer_interface null_xfer;
+extern struct xfer_interface_operations null_xfer_ops;
+
+extern void xfer_close ( struct xfer_interface *xfer, int rc );
+extern int xfer_vredirect ( struct xfer_interface *xfer, int type,
+ va_list args );
+extern int xfer_redirect ( struct xfer_interface *xfer, int type, ... );
+extern size_t xfer_window ( struct xfer_interface *xfer );
+extern struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer,
+ size_t len );
+extern int xfer_deliver_iob ( struct xfer_interface *xfer,
+ struct io_buffer *iobuf );
+extern int xfer_deliver_iob_meta ( struct xfer_interface *xfer,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta );
+extern int xfer_deliver_raw ( struct xfer_interface *xfer,
+ const void *data, size_t len );
+extern int xfer_vprintf ( struct xfer_interface *xfer,
+ const char *format, va_list args );
+extern int xfer_printf ( struct xfer_interface *xfer,
+ const char *format, ... );
+extern int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence );
+
+extern void ignore_xfer_close ( struct xfer_interface *xfer, int rc );
+extern int ignore_xfer_vredirect ( struct xfer_interface *xfer,
+ int type, va_list args );
+extern size_t unlimited_xfer_window ( struct xfer_interface *xfer );
+extern size_t no_xfer_window ( struct xfer_interface *xfer );
+extern struct io_buffer * default_xfer_alloc_iob ( struct xfer_interface *xfer,
+ size_t len );
+extern int xfer_deliver_as_raw ( struct xfer_interface *xfer,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta );
+extern int xfer_deliver_as_iob ( struct xfer_interface *xfer,
+ const void *data, size_t len );
+extern int ignore_xfer_deliver_raw ( struct xfer_interface *xfer,
+ const void *data __unused, size_t len );
+
+/**
+ * Initialise a data transfer interface
+ *
+ * @v xfer Data transfer interface
+ * @v op Data transfer interface operations
+ * @v refcnt Containing object reference counter, or NULL
+ */
+static inline void xfer_init ( struct xfer_interface *xfer,
+ struct xfer_interface_operations *op,
+ struct refcnt *refcnt ) {
+ xfer->intf.dest = &null_xfer.intf;
+ xfer->intf.refcnt = refcnt;
+ xfer->op = op;
+}
+
+/**
+ * Initialise a static data transfer interface
+ *
+ * @v operations Data transfer interface operations
+ */
+#define XFER_INIT( operations ) { \
+ .intf = { \
+ .dest = &null_xfer.intf, \
+ .refcnt = NULL, \
+ }, \
+ .op = operations, \
+ }
+
+/**
+ * Get data transfer interface from generic object communication interface
+ *
+ * @v intf Generic object communication interface
+ * @ret xfer Data transfer interface
+ */
+static inline __attribute__ (( always_inline )) struct xfer_interface *
+intf_to_xfer ( struct interface *intf ) {
+ return container_of ( intf, struct xfer_interface, intf );
+}
+
+/**
+ * Get reference to destination data transfer interface
+ *
+ * @v xfer Data transfer interface
+ * @ret dest Destination interface
+ */
+static inline __attribute__ (( always_inline )) struct xfer_interface *
+xfer_get_dest ( struct xfer_interface *xfer ) {
+ return intf_to_xfer ( intf_get ( xfer->intf.dest ) );
+}
+
+/**
+ * Drop reference to data transfer interface
+ *
+ * @v xfer Data transfer interface
+ */
+static inline __attribute__ (( always_inline )) void
+xfer_put ( struct xfer_interface *xfer ) {
+ intf_put ( &xfer->intf );
+}
+
+/**
+ * Plug a data transfer interface into a new destination interface
+ *
+ * @v xfer Data transfer interface
+ * @v dest New destination interface
+ */
+static inline __attribute__ (( always_inline )) void
+xfer_plug ( struct xfer_interface *xfer, struct xfer_interface *dest ) {
+ plug ( &xfer->intf, &dest->intf );
+}
+
+/**
+ * Plug two data transfer interfaces together
+ *
+ * @v a Data transfer interface A
+ * @v b Data transfer interface B
+ */
+static inline __attribute__ (( always_inline )) void
+xfer_plug_plug ( struct xfer_interface *a, struct xfer_interface *b ) {
+ plug_plug ( &a->intf, &b->intf );
+}
+
+/**
+ * Unplug a data transfer interface
+ *
+ * @v xfer Data transfer interface
+ */
+static inline __attribute__ (( always_inline )) void
+xfer_unplug ( struct xfer_interface *xfer ) {
+ plug ( &xfer->intf, &null_xfer.intf );
+}
+
+/**
+ * Stop using a data transfer interface
+ *
+ * @v xfer Data transfer interface
+ *
+ * After calling this method, no further messages will be received via
+ * the interface.
+ */
+static inline void xfer_nullify ( struct xfer_interface *xfer ) {
+ xfer->op = &null_xfer_ops;
+};
+
+#endif /* _GPXE_XFER_H */
diff --git a/gpxe/src/include/i82365.h b/gpxe/src/include/i82365.h
new file mode 100644
index 00000000..3b0e00ca
--- /dev/null
+++ b/gpxe/src/include/i82365.h
@@ -0,0 +1,450 @@
+/*
+ * i82365.h 1.15 1999/10/25 20:03:34
+ *
+ * The contents of this file may be used under the
+ * terms of the GNU General Public License version 2 (the "GPL").
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ */
+
+#ifndef _LINUX_I82365_H
+#define _LINUX_I82365_H
+
+/* register definitions for the Intel 82365SL PCMCIA controller */
+
+/* Offsets for PCIC registers */
+#define I365_IDENT 0x00 /* Identification and revision */
+#define I365_STATUS 0x01 /* Interface status */
+#define I365_POWER 0x02 /* Power and RESETDRV control */
+#define I365_INTCTL 0x03 /* Interrupt and general control */
+#define I365_CSC 0x04 /* Card status change */
+#define I365_CSCINT 0x05 /* Card status change interrupt control */
+#define I365_ADDRWIN 0x06 /* Address window enable */
+#define I365_IOCTL 0x07 /* I/O control */
+#define I365_GENCTL 0x16 /* Card detect and general control */
+#define I365_GBLCTL 0x1E /* Global control register */
+
+/* Offsets for I/O and memory window registers */
+#define I365_IO(map) (0x08+((map)<<2))
+#define I365_MEM(map) (0x10+((map)<<3))
+#define I365_W_START 0
+#define I365_W_STOP 2
+#define I365_W_OFF 4
+
+/* Flags for I365_STATUS */
+#define I365_CS_BVD1 0x01
+#define I365_CS_STSCHG 0x01
+#define I365_CS_BVD2 0x02
+#define I365_CS_SPKR 0x02
+#define I365_CS_DETECT 0x0C
+#define I365_CS_WRPROT 0x10
+#define I365_CS_READY 0x20 /* Inverted */
+#define I365_CS_POWERON 0x40
+#define I365_CS_GPI 0x80
+
+/* Flags for I365_POWER */
+#define I365_PWR_OFF 0x00 /* Turn off the socket */
+#define I365_PWR_OUT 0x80 /* Output enable */
+#define I365_PWR_NORESET 0x40 /* Disable RESETDRV on resume */
+#define I365_PWR_AUTO 0x20 /* Auto pwr switch enable */
+#define I365_VCC_MASK 0x18 /* Mask for turning off Vcc */
+/* There are different layouts for B-step and DF-step chips: the B
+ step has independent Vpp1/Vpp2 control, and the DF step has only
+ Vpp1 control, plus 3V control */
+#define I365_VCC_5V 0x10 /* Vcc = 5.0v */
+#define I365_VCC_3V 0x18 /* Vcc = 3.3v */
+#define I365_VPP2_MASK 0x0c /* Mask for turning off Vpp2 */
+#define I365_VPP2_5V 0x04 /* Vpp2 = 5.0v */
+#define I365_VPP2_12V 0x08 /* Vpp2 = 12.0v */
+#define I365_VPP1_MASK 0x03 /* Mask for turning off Vpp1 */
+#define I365_VPP1_5V 0x01 /* Vpp2 = 5.0v */
+#define I365_VPP1_12V 0x02 /* Vpp2 = 12.0v */
+
+/* Flags for I365_INTCTL */
+#define I365_RING_ENA 0x80
+#define I365_PC_RESET 0x40
+#define I365_PC_IOCARD 0x20
+#define I365_INTR_ENA 0x10
+#define I365_IRQ_MASK 0x0F
+
+/* Flags for I365_CSC and I365_CSCINT*/
+#define I365_CSC_BVD1 0x01
+#define I365_CSC_STSCHG 0x01
+#define I365_CSC_BVD2 0x02
+#define I365_CSC_READY 0x04
+#define I365_CSC_DETECT 0x08
+#define I365_CSC_ANY 0x0F
+#define I365_CSC_GPI 0x10
+
+/* Flags for I365_ADDRWIN */
+#define I365_ENA_IO(map) (0x40 << (map))
+#define I365_ENA_MEM(map) (0x01 << (map))
+
+/* Flags for I365_IOCTL */
+#define I365_IOCTL_MASK(map) (0x0F << (map<<2))
+#define I365_IOCTL_WAIT(map) (0x08 << (map<<2))
+#define I365_IOCTL_0WS(map) (0x04 << (map<<2))
+#define I365_IOCTL_IOCS16(map) (0x02 << (map<<2))
+#define I365_IOCTL_16BIT(map) (0x01 << (map<<2))
+
+/* Flags for I365_GENCTL */
+#define I365_CTL_16DELAY 0x01
+#define I365_CTL_RESET 0x02
+#define I365_CTL_GPI_ENA 0x04
+#define I365_CTL_GPI_CTL 0x08
+#define I365_CTL_RESUME 0x10
+#define I365_CTL_SW_IRQ 0x20
+
+/* Flags for I365_GBLCTL */
+#define I365_GBL_PWRDOWN 0x01
+#define I365_GBL_CSC_LEV 0x02
+#define I365_GBL_WRBACK 0x04
+#define I365_GBL_IRQ_0_LEV 0x08
+#define I365_GBL_IRQ_1_LEV 0x10
+
+/* Flags for memory window registers */
+#define I365_MEM_16BIT 0x8000 /* In memory start high byte */
+#define I365_MEM_0WS 0x4000
+#define I365_MEM_WS1 0x8000 /* In memory stop high byte */
+#define I365_MEM_WS0 0x4000
+#define I365_MEM_WRPROT 0x8000 /* In offset high byte */
+#define I365_MEM_REG 0x4000
+
+#define I365_REG(slot, reg) (((slot) << 6) + reg)
+
+#endif /* _LINUX_I82365_H */
+
+//*****************************************************************************
+//*****************************************************************************
+//*****************************************************************************
+//*****************************************************************************
+//*****************************************************************************
+// Beginning vg468.h (for VADEM chipset)
+
+#ifndef _LINUX_VG468_H
+#define _LINUX_VG468_H
+
+/* Special bit in I365_IDENT used for Vadem chip detection */
+#define I365_IDENT_VADEM 0x08
+
+/* Special definitions in I365_POWER */
+#define VG468_VPP2_MASK 0x0c
+#define VG468_VPP2_5V 0x04
+#define VG468_VPP2_12V 0x08
+
+/* Unique Vadem registers */
+#define VG469_VSENSE 0x1f /* Card voltage sense */
+#define VG469_VSELECT 0x2f /* Card voltage select */
+#define VG468_CTL 0x38 /* Control register */
+#define VG468_TIMER 0x39 /* Timer control */
+#define VG468_MISC 0x3a /* Miscellaneous */
+#define VG468_GPIO_CFG 0x3b /* GPIO configuration */
+#define VG469_EXT_MODE 0x3c /* Extended mode register */
+#define VG468_SELECT 0x3d /* Programmable chip select */
+#define VG468_SELECT_CFG 0x3e /* Chip select configuration */
+#define VG468_ATA 0x3f /* ATA control */
+
+/* Flags for VG469_VSENSE */
+#define VG469_VSENSE_A_VS1 0x01
+#define VG469_VSENSE_A_VS2 0x02
+#define VG469_VSENSE_B_VS1 0x04
+#define VG469_VSENSE_B_VS2 0x08
+
+/* Flags for VG469_VSELECT */
+#define VG469_VSEL_VCC 0x03
+#define VG469_VSEL_5V 0x00
+#define VG469_VSEL_3V 0x03
+#define VG469_VSEL_MAX 0x0c
+#define VG469_VSEL_EXT_STAT 0x10
+#define VG469_VSEL_EXT_BUS 0x20
+#define VG469_VSEL_MIXED 0x40
+#define VG469_VSEL_ISA 0x80
+
+/* Flags for VG468_CTL */
+#define VG468_CTL_SLOW 0x01 /* 600ns memory timing */
+#define VG468_CTL_ASYNC 0x02 /* Asynchronous bus clocking */
+#define VG468_CTL_TSSI 0x08 /* Tri-state some outputs */
+#define VG468_CTL_DELAY 0x10 /* Card detect debounce */
+#define VG468_CTL_INPACK 0x20 /* Obey INPACK signal? */
+#define VG468_CTL_POLARITY 0x40 /* VCCEN polarity */
+#define VG468_CTL_COMPAT 0x80 /* Compatibility stuff */
+
+#define VG469_CTL_WS_COMPAT 0x04 /* Wait state compatibility */
+#define VG469_CTL_STRETCH 0x10 /* LED stretch */
+
+/* Flags for VG468_TIMER */
+#define VG468_TIMER_ZEROPWR 0x10 /* Zero power control */
+#define VG468_TIMER_SIGEN 0x20 /* Power up */
+#define VG468_TIMER_STATUS 0x40 /* Activity timer status */
+#define VG468_TIMER_RES 0x80 /* Timer resolution */
+#define VG468_TIMER_MASK 0x0f /* Activity timer timeout */
+
+/* Flags for VG468_MISC */
+#define VG468_MISC_GPIO 0x04 /* General-purpose IO */
+#define VG468_MISC_DMAWSB 0x08 /* DMA wait state control */
+#define VG469_MISC_LEDENA 0x10 /* LED enable */
+#define VG468_MISC_VADEMREV 0x40 /* Vadem revision control */
+#define VG468_MISC_UNLOCK 0x80 /* Unique register lock */
+
+/* Flags for VG469_EXT_MODE_A */
+#define VG469_MODE_VPPST 0x03 /* Vpp steering control */
+#define VG469_MODE_INT_SENSE 0x04 /* Internal voltage sense */
+#define VG469_MODE_CABLE 0x08
+#define VG469_MODE_COMPAT 0x10 /* i82365sl B or DF step */
+#define VG469_MODE_TEST 0x20
+#define VG469_MODE_RIO 0x40 /* Steer RIO to INTR? */
+
+/* Flags for VG469_EXT_MODE_B */
+#define VG469_MODE_B_3V 0x01 /* 3.3v for socket B */
+
+#endif /* _LINUX_VG468_H */
+
+
+//*****************************************************************************
+//*****************************************************************************
+//*****************************************************************************
+//*****************************************************************************
+//*****************************************************************************
+// Beginning ricoh.h (RICOH chipsets)
+
+#ifndef _LINUX_RICOH_H
+#define _LINUX_RICOH_H
+
+
+#define RF5C_MODE_CTL 0x1f /* Mode control */
+#define RF5C_PWR_CTL 0x2f /* Mixed voltage control */
+#define RF5C_CHIP_ID 0x3a /* Chip identification */
+#define RF5C_MODE_CTL_3 0x3b /* Mode control 3 */
+
+/* I/O window address offset */
+#define RF5C_IO_OFF(w) (0x36+((w)<<1))
+
+/* Flags for RF5C_MODE_CTL */
+#define RF5C_MODE_ATA 0x01 /* ATA mode */
+#define RF5C_MODE_LED_ENA 0x02 /* IRQ 12 is LED */
+#define RF5C_MODE_CA21 0x04
+#define RF5C_MODE_CA22 0x08
+#define RF5C_MODE_CA23 0x10
+#define RF5C_MODE_CA24 0x20
+#define RF5C_MODE_CA25 0x40
+#define RF5C_MODE_3STATE_BIT7 0x80
+
+/* Flags for RF5C_PWR_CTL */
+#define RF5C_PWR_VCC_3V 0x01
+#define RF5C_PWR_IREQ_HIGH 0x02
+#define RF5C_PWR_INPACK_ENA 0x04
+#define RF5C_PWR_5V_DET 0x08
+#define RF5C_PWR_TC_SEL 0x10 /* Terminal Count: irq 11 or 15 */
+#define RF5C_PWR_DREQ_LOW 0x20
+#define RF5C_PWR_DREQ_OFF 0x00 /* DREQ steering control */
+#define RF5C_PWR_DREQ_INPACK 0x40
+#define RF5C_PWR_DREQ_SPKR 0x80
+#define RF5C_PWR_DREQ_IOIS16 0xc0
+
+/* Values for RF5C_CHIP_ID */
+#define RF5C_CHIP_RF5C296 0x32
+#define RF5C_CHIP_RF5C396 0xb2
+
+/* Flags for RF5C_MODE_CTL_3 */
+#define RF5C_MCTL3_DISABLE 0x01 /* Disable PCMCIA interface */
+#define RF5C_MCTL3_DMA_ENA 0x02
+
+/* Register definitions for Ricoh PCI-to-CardBus bridges */
+
+/* Extra bits in CB_BRIDGE_CONTROL */
+#define RL5C46X_BCR_3E0_ENA 0x0800
+#define RL5C46X_BCR_3E2_ENA 0x1000
+
+/* Bridge Configuration Register */
+#define RL5C4XX_CONFIG 0x80 /* 16 bit */
+#define RL5C4XX_CONFIG_IO_1_MODE 0x0200
+#define RL5C4XX_CONFIG_IO_0_MODE 0x0100
+#define RL5C4XX_CONFIG_PREFETCH 0x0001
+
+
+/* Misc Control Register */
+#define RL5C4XX_MISC 0x0082 /* 16 bit */
+#define RL5C4XX_MISC_HW_SUSPEND_ENA 0x0002
+#define RL5C4XX_MISC_VCCEN_POL 0x0100
+#define RL5C4XX_MISC_VPPEN_POL 0x0200
+#define RL5C46X_MISC_SUSPEND 0x0001
+#define RL5C46X_MISC_PWR_SAVE_2 0x0004
+#define RL5C46X_MISC_IFACE_BUSY 0x0008
+#define RL5C46X_MISC_B_LOCK 0x0010
+#define RL5C46X_MISC_A_LOCK 0x0020
+#define RL5C46X_MISC_PCI_LOCK 0x0040
+#define RL5C47X_MISC_IFACE_BUSY 0x0004
+#define RL5C47X_MISC_PCI_INT_MASK 0x0018
+#define RL5C47X_MISC_PCI_INT_DIS 0x0020
+#define RL5C47X_MISC_SUBSYS_WR 0x0040
+#define RL5C47X_MISC_SRIRQ_ENA 0x0080
+#define RL5C47X_MISC_5V_DISABLE 0x0400
+#define RL5C47X_MISC_LED_POL 0x0800
+
+/* 16-bit Interface Control Register */
+#define RL5C4XX_16BIT_CTL 0x0084 /* 16 bit */
+#define RL5C4XX_16CTL_IO_TIMING 0x0100
+#define RL5C4XX_16CTL_MEM_TIMING 0x0200
+#define RL5C46X_16CTL_LEVEL_1 0x0010
+#define RL5C46X_16CTL_LEVEL_2 0x0020
+
+/* 16-bit IO and memory timing registers */
+#define RL5C4XX_16BIT_IO_0 0x0088 /* 16 bit */
+#define RL5C4XX_16BIT_MEM_0 0x0088 /* 16 bit */
+#define RL5C4XX_SETUP_MASK 0x0007
+#define RL5C4XX_SETUP_SHIFT 0
+#define RL5C4XX_CMD_MASK 0x01f0
+#define RL5C4XX_CMD_SHIFT 4
+#define RL5C4XX_HOLD_MASK 0x1c00
+#define RL5C4XX_HOLD_SHIFT 10
+#define RL5C4XX_MISC_CONTROL 0x2F /* 8 bit */
+#define RL5C4XX_ZV_ENABLE 0x08
+
+#endif /* _LINUX_RICOH_H */
+
+
+//*****************************************************************************
+//*****************************************************************************
+//*****************************************************************************
+//*****************************************************************************
+//*****************************************************************************
+// Beginning cirrus.h (CIRRUS chipsets)
+
+#ifndef _LINUX_CIRRUS_H
+#define _LINUX_CIRRUS_H
+
+#ifndef PCI_VENDOR_ID_CIRRUS
+#define PCI_VENDOR_ID_CIRRUS 0x1013
+#endif
+#ifndef PCI_DEVICE_ID_CIRRUS_6729
+#define PCI_DEVICE_ID_CIRRUS_6729 0x1100
+#endif
+#ifndef PCI_DEVICE_ID_CIRRUS_6832
+#define PCI_DEVICE_ID_CIRRUS_6832 0x1110
+#endif
+
+#define PD67_MISC_CTL_1 0x16 /* Misc control 1 */
+#define PD67_FIFO_CTL 0x17 /* FIFO control */
+#define PD67_MISC_CTL_2 0x1E /* Misc control 2 */
+#define PD67_CHIP_INFO 0x1f /* Chip information */
+#define PD67_ATA_CTL 0x026 /* 6730: ATA control */
+#define PD67_EXT_INDEX 0x2e /* Extension index */
+#define PD67_EXT_DATA 0x2f /* Extension data */
+
+/* PD6722 extension registers -- indexed in PD67_EXT_INDEX */
+#define PD67_DATA_MASK0 0x01 /* Data mask 0 */
+#define PD67_DATA_MASK1 0x02 /* Data mask 1 */
+#define PD67_DMA_CTL 0x03 /* DMA control */
+
+/* PD6730 extension registers -- indexed in PD67_EXT_INDEX */
+#define PD67_EXT_CTL_1 0x03 /* Extension control 1 */
+#define PD67_MEM_PAGE(n) ((n)+5) /* PCI window bits 31:24 */
+#define PD67_EXTERN_DATA 0x0a
+#define PD67_MISC_CTL_3 0x25
+#define PD67_SMB_PWR_CTL 0x26
+
+/* I/O window address offset */
+#define PD67_IO_OFF(w) (0x36+((w)<<1))
+
+/* Timing register sets */
+#define PD67_TIME_SETUP(n) (0x3a + 3*(n))
+#define PD67_TIME_CMD(n) (0x3b + 3*(n))
+#define PD67_TIME_RECOV(n) (0x3c + 3*(n))
+
+/* Flags for PD67_MISC_CTL_1 */
+#define PD67_MC1_5V_DET 0x01 /* 5v detect */
+#define PD67_MC1_MEDIA_ENA 0x01 /* 6730: Multimedia enable */
+#define PD67_MC1_VCC_3V 0x02 /* 3.3v Vcc */
+#define PD67_MC1_PULSE_MGMT 0x04
+#define PD67_MC1_PULSE_IRQ 0x08
+#define PD67_MC1_SPKR_ENA 0x10
+#define PD67_MC1_INPACK_ENA 0x80
+
+/* Flags for PD67_FIFO_CTL */
+#define PD67_FIFO_EMPTY 0x80
+
+/* Flags for PD67_MISC_CTL_2 */
+#define PD67_MC2_FREQ_BYPASS 0x01
+#define PD67_MC2_DYNAMIC_MODE 0x02
+#define PD67_MC2_SUSPEND 0x04
+#define PD67_MC2_5V_CORE 0x08
+#define PD67_MC2_LED_ENA 0x10 /* IRQ 12 is LED enable */
+#define PD67_MC2_FAST_PCI 0x10 /* 6729: PCI bus > 25 MHz */
+#define PD67_MC2_3STATE_BIT7 0x20 /* Floppy change bit */
+#define PD67_MC2_DMA_MODE 0x40
+#define PD67_MC2_IRQ15_RI 0x80 /* IRQ 15 is ring enable */
+
+/* Flags for PD67_CHIP_INFO */
+#define PD67_INFO_SLOTS 0x20 /* 0 = 1 slot, 1 = 2 slots */
+#define PD67_INFO_CHIP_ID 0xc0
+#define PD67_INFO_REV 0x1c
+
+/* Fields in PD67_TIME_* registers */
+#define PD67_TIME_SCALE 0xc0
+#define PD67_TIME_SCALE_1 0x00
+#define PD67_TIME_SCALE_16 0x40
+#define PD67_TIME_SCALE_256 0x80
+#define PD67_TIME_SCALE_4096 0xc0
+#define PD67_TIME_MULT 0x3f
+
+/* Fields in PD67_DMA_CTL */
+#define PD67_DMA_MODE 0xc0
+#define PD67_DMA_OFF 0x00
+#define PD67_DMA_DREQ_INPACK 0x40
+#define PD67_DMA_DREQ_WP 0x80
+#define PD67_DMA_DREQ_BVD2 0xc0
+#define PD67_DMA_PULLUP 0x20 /* Disable socket pullups? */
+
+/* Fields in PD67_EXT_CTL_1 */
+#define PD67_EC1_VCC_PWR_LOCK 0x01
+#define PD67_EC1_AUTO_PWR_CLEAR 0x02
+#define PD67_EC1_LED_ENA 0x04
+#define PD67_EC1_INV_CARD_IRQ 0x08
+#define PD67_EC1_INV_MGMT_IRQ 0x10
+#define PD67_EC1_PULLUP_CTL 0x20
+
+/* Fields in PD67_MISC_CTL_3 */
+#define PD67_MC3_IRQ_MASK 0x03
+#define PD67_MC3_IRQ_PCPCI 0x00
+#define PD67_MC3_IRQ_EXTERN 0x01
+#define PD67_MC3_IRQ_PCIWAY 0x02
+#define PD67_MC3_IRQ_PCI 0x03
+#define PD67_MC3_PWR_MASK 0x0c
+#define PD67_MC3_PWR_SERIAL 0x00
+#define PD67_MC3_PWR_TI2202 0x08
+#define PD67_MC3_PWR_SMB 0x0c
+
+/* Register definitions for Cirrus PD6832 PCI-to-CardBus bridge */
+
+/* PD6832 extension registers -- indexed in PD67_EXT_INDEX */
+#define PD68_EXT_CTL_2 0x0b
+#define PD68_PCI_SPACE 0x22
+#define PD68_PCCARD_SPACE 0x23
+#define PD68_WINDOW_TYPE 0x24
+#define PD68_EXT_CSC 0x2e
+#define PD68_MISC_CTL_4 0x2f
+#define PD68_MISC_CTL_5 0x30
+#define PD68_MISC_CTL_6 0x31
+
+/* Extra flags in PD67_MISC_CTL_3 */
+#define PD68_MC3_HW_SUSP 0x10
+#define PD68_MC3_MM_EXPAND 0x40
+#define PD68_MC3_MM_ARM 0x80
+
+/* Bridge Control Register */
+#define PD6832_BCR_MGMT_IRQ_ENA 0x0800
+
+/* Socket Number Register */
+#define PD6832_SOCKET_NUMBER 0x004c /* 8 bit */
+
+#endif /* _LINUX_CIRRUS_H */
+
+
+
diff --git a/gpxe/src/include/igmp.h b/gpxe/src/include/igmp.h
new file mode 100644
index 00000000..8b3292f2
--- /dev/null
+++ b/gpxe/src/include/igmp.h
@@ -0,0 +1,42 @@
+#ifndef IGMP_H
+#define IGMP_H
+
+#include "stdint.h"
+#include <gpxe/in.h>
+
+#define IGMP_QUERY 0x11
+#define IGMPv1_REPORT 0x12
+#define IGMPv2_REPORT 0x16
+#define IGMP_LEAVE 0x17
+#define GROUP_ALL_HOSTS 0xe0000001 /* 224.0.0.1 Host byte order */
+
+#define MULTICAST_MASK 0xf0000000
+#define MULTICAST_NETWORK 0xe0000000
+
+enum {
+ IGMP_SERVER,
+ MAX_IGMP
+};
+
+struct igmp {
+ uint8_t type;
+ uint8_t response_time;
+ uint16_t chksum;
+ struct in_addr group;
+} PACKED;
+
+struct igmp_ip_t { /* Format of an igmp ip packet */
+ struct iphdr ip;
+ uint8_t router_alert[4]; /* Router alert option */
+ struct igmp igmp;
+} PACKED;
+
+struct igmptable_t {
+ struct in_addr group;
+ unsigned long time;
+} PACKED;
+
+extern void join_group ( int slot, unsigned long group );
+extern void leave_group ( int slot );
+
+#endif /* IGMP_H */
diff --git a/gpxe/src/include/lib.h b/gpxe/src/include/lib.h
new file mode 100644
index 00000000..400ea468
--- /dev/null
+++ b/gpxe/src/include/lib.h
@@ -0,0 +1,42 @@
+#ifndef LIB_H
+#define LIB_H
+
+#include <stdint.h>
+
+int getline(char *buf, int max);
+
+extern struct pci_device *dev_list;
+extern int n_devs;
+
+extern void pci_init(void);
+extern struct pci_device *pci_find_device(int vendor, int device, int devclass,
+int prog_if, int index);
+
+void *calloc(size_t nmemb, size_t size);
+void *realloc(void *ptr, size_t size);
+
+char *strdup(const char *s);
+
+int isspace(int c);
+
+unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base);
+unsigned long long strtoull_with_suffix(const char *cp,char **endp,unsigned int base);
+
+unsigned int get_le32(const unsigned char *);
+unsigned int get_le16(const unsigned char *);
+void hexdump(const void *p, unsigned int len);
+
+long long simple_strtoll(const char *cp,char **endp,unsigned int base);
+
+#define LOADER_NOT_SUPPORT 0xbadf11e
+
+struct sys_info;
+int elf_load(struct sys_info *, const char *filename, const char *cmdline);
+
+#if LINUX_LOADER
+int linux_load(struct sys_info *, const char *filename, const char *cmdline);
+#else
+#define linux_load(x,y,z) LOADER_NOT_SUPPORT /* nop */
+#endif
+
+#endif /* LIB_H */
diff --git a/gpxe/src/include/libgen.h b/gpxe/src/include/libgen.h
new file mode 100644
index 00000000..56a2f760
--- /dev/null
+++ b/gpxe/src/include/libgen.h
@@ -0,0 +1,7 @@
+#ifndef _LIBGEN_H
+#define _LIBGEN_H
+
+extern char * basename ( char *path );
+extern char * dirname ( char *path );
+
+#endif /* _LIBGEN_H */
diff --git a/gpxe/src/include/little_bswap.h b/gpxe/src/include/little_bswap.h
new file mode 100644
index 00000000..e4f83753
--- /dev/null
+++ b/gpxe/src/include/little_bswap.h
@@ -0,0 +1,33 @@
+#ifndef ETHERBOOT_LITTLE_BSWAP_H
+#define ETHERBOOT_LITTLE_BSWAP_H
+
+#define ntohl(x) __bswap_32(x)
+#define htonl(x) __bswap_32(x)
+#define ntohs(x) __bswap_16(x)
+#define htons(x) __bswap_16(x)
+#define cpu_to_le64(x) (x)
+#define cpu_to_le32(x) (x)
+#define cpu_to_le16(x) (x)
+#define cpu_to_be64(x) __bswap_64(x)
+#define cpu_to_be32(x) __bswap_32(x)
+#define cpu_to_be16(x) __bswap_16(x)
+#define le64_to_cpu(x) (x)
+#define le32_to_cpu(x) (x)
+#define le16_to_cpu(x) (x)
+#define be64_to_cpu(x) __bswap_64(x)
+#define be32_to_cpu(x) __bswap_32(x)
+#define be16_to_cpu(x) __bswap_16(x)
+#define cpu_to_le64s(x) do {} while (0)
+#define cpu_to_le32s(x) do {} while (0)
+#define cpu_to_le16s(x) do {} while (0)
+#define cpu_to_be64s(x) __bswap_64s(x)
+#define cpu_to_be32s(x) __bswap_32s(x)
+#define cpu_to_be16s(x) __bswap_16s(x)
+#define le64_to_cpus(x) do {} while (0)
+#define le32_to_cpus(x) do {} while (0)
+#define le16_to_cpus(x) do {} while (0)
+#define be64_to_cpus(x) __bswap_64s(x)
+#define be32_to_cpus(x) __bswap_32s(x)
+#define be16_to_cpus(x) __bswap_16s(x)
+
+#endif /* ETHERBOOT_LITTLE_BSWAP_H */
diff --git a/gpxe/src/include/mii.h b/gpxe/src/include/mii.h
new file mode 100644
index 00000000..34c1ca9b
--- /dev/null
+++ b/gpxe/src/include/mii.h
@@ -0,0 +1,105 @@
+/*
+ * linux/mii.h: definitions for MII-compatible transceivers
+ * Originally drivers/net/sunhme.h.
+ *
+ * Copyright (C) 1996, 1999, 2001 David S. Miller (davem@redhat.com)
+ *
+ * Copied Form Linux 2.4.25 an unneeded items removed by:
+ * Timothy Legge (timlegge at etherboot dot org)
+ *
+ * 03/26/2004
+ */
+
+/* Generic MII registers. */
+
+#define MII_BMCR 0x00 /* Basic mode control register */
+#define MII_BMSR 0x01 /* Basic mode status register */
+#define MII_PHYSID1 0x02 /* PHYS ID 1 */
+#define MII_PHYSID2 0x03 /* PHYS ID 2 */
+#define MII_ADVERTISE 0x04 /* Advertisement control reg */
+#define MII_LPA 0x05 /* Link partner ability reg */
+#define MII_EXPANSION 0x06 /* Expansion register */
+#define MII_DCOUNTER 0x12 /* Disconnect counter */
+#define MII_FCSCOUNTER 0x13 /* False carrier counter */
+#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
+#define MII_RERRCOUNTER 0x15 /* Receive error counter */
+#define MII_SREVISION 0x16 /* Silicon revision */
+#define MII_RESV1 0x17 /* Reserved... */
+#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
+#define MII_PHYADDR 0x19 /* PHY address */
+#define MII_RESV2 0x1a /* Reserved... */
+#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
+#define MII_NCONFIG 0x1c /* Network interface config */
+
+/* Basic mode control register. */
+#define BMCR_RESV 0x007f /* Unused... */
+#define BMCR_CTST 0x0080 /* Collision test */
+#define BMCR_FULLDPLX 0x0100 /* Full duplex */
+#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
+#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
+#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
+#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
+#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
+#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
+#define BMCR_RESET 0x8000 /* Reset the DP83840 */
+
+/* Basic mode status register. */
+#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
+#define BMSR_JCD 0x0002 /* Jabber detected */
+#define BMSR_LSTATUS 0x0004 /* Link status */
+#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
+#define BMSR_RFAULT 0x0010 /* Remote fault detected */
+#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
+#define BMSR_RESV 0x07c0 /* Unused... */
+#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
+#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
+#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
+#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
+#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
+
+/* Advertisement control register. */
+#define ADVERTISE_SLCT 0x001f /* Selector bits */
+#define ADVERTISE_CSMA 0x0001 /* Only selector supported */
+#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
+#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
+#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
+#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
+#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
+#define ADVERTISE_RESV 0x1c00 /* Unused... */
+#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
+#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
+#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
+
+#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
+ ADVERTISE_CSMA)
+#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
+ ADVERTISE_100HALF | ADVERTISE_100FULL)
+
+/* Link partner ability register. */
+#define LPA_SLCT 0x001f /* Same as advertise selector */
+#define LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
+#define LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
+#define LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
+#define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
+#define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */
+#define LPA_RESV 0x1c00 /* Unused... */
+#define LPA_RFAULT 0x2000 /* Link partner faulted */
+#define LPA_LPACK 0x4000 /* Link partner acked us */
+#define LPA_NPAGE 0x8000 /* Next page bit */
+
+#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL)
+#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4)
+
+/* Expansion register for auto-negotiation. */
+#define EXPANSION_NWAY 0x0001 /* Can do N-way auto-nego */
+#define EXPANSION_LCWP 0x0002 /* Got new RX page code word */
+#define EXPANSION_ENABLENPAGE 0x0004 /* This enables npage words */
+#define EXPANSION_NPCAPABLE 0x0008 /* Link partner supports npage */
+#define EXPANSION_MFAULTS 0x0010 /* Multiple faults detected */
+#define EXPANSION_RESV 0xffe0 /* Unused... */
+
+/* N-way test register. */
+#define NWAYTEST_RESV1 0x00ff /* Unused... */
+#define NWAYTEST_LOOPBACK 0x0100 /* Enable loopback for N-way */
+#define NWAYTEST_RESV2 0xfe00 /* Unused... */
+
diff --git a/gpxe/src/include/nfs.h b/gpxe/src/include/nfs.h
new file mode 100644
index 00000000..0877bb66
--- /dev/null
+++ b/gpxe/src/include/nfs.h
@@ -0,0 +1,63 @@
+#ifndef _NFS_H
+#define _NFS_H
+
+#define SUNRPC_PORT 111
+
+#define PROG_PORTMAP 100000
+#define PROG_NFS 100003
+#define PROG_MOUNT 100005
+
+#define MSG_CALL 0
+#define MSG_REPLY 1
+
+#define PORTMAP_GETPORT 3
+
+#define MOUNT_ADDENTRY 1
+#define MOUNT_UMOUNTALL 4
+
+#define NFS_LOOKUP 4
+#define NFS_READLINK 5
+#define NFS_READ 6
+
+#define NFS_FHSIZE 32
+
+#define NFSERR_PERM 1
+#define NFSERR_NOENT 2
+#define NFSERR_ACCES 13
+#define NFSERR_ISDIR 21
+#define NFSERR_INVAL 22
+
+/* Block size used for NFS read accesses. A RPC reply packet (including all
+ * headers) must fit within a single Ethernet frame to avoid fragmentation.
+ * Chosen to be a power of two, as most NFS servers are optimized for this. */
+#define NFS_READ_SIZE 1024
+
+#define NFS_MAXLINKDEPTH 16
+
+struct rpc_t {
+ struct iphdr ip;
+ struct udphdr udp;
+ union {
+ uint8_t data[300]; /* longest RPC call must fit!!!! */
+ struct {
+ uint32_t id;
+ uint32_t type;
+ uint32_t rpcvers;
+ uint32_t prog;
+ uint32_t vers;
+ uint32_t proc;
+ uint32_t data[1];
+ } call;
+ struct {
+ uint32_t id;
+ uint32_t type;
+ uint32_t rstatus;
+ uint32_t verifier;
+ uint32_t v2;
+ uint32_t astatus;
+ uint32_t data[1];
+ } reply;
+ } u;
+} PACKED;
+
+#endif /* _NFS_H */
diff --git a/gpxe/src/include/nic.h b/gpxe/src/include/nic.h
new file mode 100644
index 00000000..65e4be71
--- /dev/null
+++ b/gpxe/src/include/nic.h
@@ -0,0 +1,272 @@
+ /*
+ * 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, or (at
+ * your option) any later version.
+ */
+
+#ifndef NIC_H
+#define NIC_H
+
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <byteswap.h>
+#include <gpxe/pci.h>
+#include <gpxe/isapnp.h>
+#include <gpxe/isa.h>
+#include <gpxe/eisa.h>
+#include <gpxe/mca.h>
+#include "dhcp.h"
+
+typedef enum {
+ DISABLE = 0,
+ ENABLE,
+ FORCE
+} irq_action_t;
+
+typedef enum duplex {
+ HALF_DUPLEX = 1,
+ FULL_DUPLEX
+} duplex_t;
+
+/*
+ * Structure returned from eth_probe and passed to other driver
+ * functions.
+ */
+struct nic {
+ struct nic_operations *nic_op;
+ int flags; /* driver specific flags */
+ unsigned char *node_addr;
+ unsigned char *packet;
+ unsigned int packetlen;
+ unsigned int ioaddr;
+ unsigned char irqno;
+ unsigned int mbps;
+ duplex_t duplex;
+ struct dhcp_dev_id dhcp_dev_id;
+ void *priv_data; /* driver private data */
+};
+
+struct nic_operations {
+ int ( *connect ) ( struct nic * );
+ int ( *poll ) ( struct nic *, int retrieve );
+ void ( *transmit ) ( struct nic *, const char *,
+ unsigned int, unsigned int, const char * );
+ void ( *irq ) ( struct nic *, irq_action_t );
+};
+
+extern struct nic nic;
+
+static inline int eth_poll ( int retrieve ) {
+ return nic.nic_op->poll ( &nic, retrieve );
+}
+
+static inline void eth_transmit ( const char *dest, unsigned int type,
+ unsigned int size, const void *packet ) {
+ nic.nic_op->transmit ( &nic, dest, type, size, packet );
+}
+
+/*
+ * Function prototypes
+ *
+ */
+extern int dummy_connect ( struct nic *nic );
+extern void dummy_irq ( struct nic *nic, irq_action_t irq_action );
+extern int legacy_probe ( void *hwdev,
+ void ( * set_drvdata ) ( void *hwdev, void *priv ),
+ struct device *dev,
+ int ( * probe ) ( struct nic *nic, void *hwdev ),
+ void ( * disable ) ( struct nic *nic, void *hwdev ));
+void legacy_remove ( void *hwdev,
+ void * ( * get_drvdata ) ( void *hwdev ),
+ void ( * disable ) ( struct nic *nic, void *hwdev ) );
+
+#define PCI_DRIVER(_name,_ids,_class) \
+ static inline int \
+ _name ## _pci_legacy_probe ( struct pci_device *pci, \
+ const struct pci_device_id *id ); \
+ static inline void \
+ _name ## _pci_legacy_remove ( struct pci_device *pci ); \
+ struct pci_driver _name __pci_driver = { \
+ .ids = _ids, \
+ .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
+ .probe = _name ## _pci_legacy_probe, \
+ .remove = _name ## _pci_legacy_remove, \
+ }; \
+ REQUIRE_OBJECT ( pci );
+
+static inline void legacy_pci_set_drvdata ( void *hwdev, void *priv ) {
+ pci_set_drvdata ( hwdev, priv );
+}
+static inline void * legacy_pci_get_drvdata ( void *hwdev ) {
+ return pci_get_drvdata ( hwdev );
+}
+
+#define ISAPNP_DRIVER(_name,_ids) \
+ static inline int \
+ _name ## _isapnp_legacy_probe ( struct isapnp_device *isapnp, \
+ const struct isapnp_device_id *id ); \
+ static inline void \
+ _name ## _isapnp_legacy_remove ( struct isapnp_device *isapnp ); \
+ struct isapnp_driver _name __isapnp_driver = { \
+ .ids = _ids, \
+ .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
+ .probe = _name ## _isapnp_legacy_probe, \
+ .remove = _name ## _isapnp_legacy_remove, \
+ }; \
+ REQUIRE_OBJECT ( isapnp );
+
+static inline void legacy_isapnp_set_drvdata ( void *hwdev, void *priv ) {
+ isapnp_set_drvdata ( hwdev, priv );
+}
+static inline void * legacy_isapnp_get_drvdata ( void *hwdev ) {
+ return isapnp_get_drvdata ( hwdev );
+}
+
+#define EISA_DRIVER(_name,_ids) \
+ static inline int \
+ _name ## _eisa_legacy_probe ( struct eisa_device *eisa, \
+ const struct eisa_device_id *id ); \
+ static inline void \
+ _name ## _eisa_legacy_remove ( struct eisa_device *eisa ); \
+ struct eisa_driver _name __eisa_driver = { \
+ .ids = _ids, \
+ .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
+ .probe = _name ## _eisa_legacy_probe, \
+ .remove = _name ## _eisa_legacy_remove, \
+ }; \
+ REQUIRE_OBJECT ( eisa );
+
+static inline void legacy_eisa_set_drvdata ( void *hwdev, void *priv ) {
+ eisa_set_drvdata ( hwdev, priv );
+}
+static inline void * legacy_eisa_get_drvdata ( void *hwdev ) {
+ return eisa_get_drvdata ( hwdev );
+}
+
+#define MCA_DRIVER(_name,_ids) \
+ static inline int \
+ _name ## _mca_legacy_probe ( struct mca_device *mca, \
+ const struct mca_device_id *id ); \
+ static inline void \
+ _name ## _mca_legacy_remove ( struct mca_device *mca ); \
+ struct mca_driver _name __mca_driver = { \
+ .ids = _ids, \
+ .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
+ .probe = _name ## _mca_legacy_probe, \
+ .remove = _name ## _mca_legacy_remove, \
+ }; \
+ REQUIRE_OBJECT ( mca );
+
+static inline void legacy_mca_set_drvdata ( void *hwdev, void *priv ) {
+ mca_set_drvdata ( hwdev, priv );
+}
+static inline void * legacy_mca_get_drvdata ( void *hwdev ) {
+ return mca_get_drvdata ( hwdev );
+}
+
+#define ISA_DRIVER(_name,_probe_addrs,_probe_addr,_vendor_id,_prod_id) \
+ static inline int \
+ _name ## _isa_legacy_probe ( struct isa_device *isa ); \
+ static inline int \
+ _name ## _isa_legacy_probe_at_addr ( struct isa_device *isa ) { \
+ if ( ! _probe_addr ( isa->ioaddr ) ) \
+ return -ENODEV; \
+ return _name ## _isa_legacy_probe ( isa ); \
+ } \
+ static inline void \
+ _name ## _isa_legacy_remove ( struct isa_device *isa ); \
+ static const char _name ## _text[]; \
+ struct isa_driver _name __isa_driver = { \
+ .name = _name ## _text, \
+ .probe_addrs = _probe_addrs, \
+ .addr_count = ( sizeof ( _probe_addrs ) / \
+ sizeof ( _probe_addrs[0] ) ), \
+ .vendor_id = _vendor_id, \
+ .prod_id = _prod_id, \
+ .probe = _name ## _isa_legacy_probe_at_addr, \
+ .remove = _name ## _isa_legacy_remove, \
+ }; \
+ REQUIRE_OBJECT ( isa );
+
+static inline void legacy_isa_set_drvdata ( void *hwdev, void *priv ) {
+ isa_set_drvdata ( hwdev, priv );
+}
+static inline void * legacy_isa_get_drvdata ( void *hwdev ) {
+ return isa_get_drvdata ( hwdev );
+}
+
+#undef DRIVER
+#define DRIVER(_name_text,_unused2,_unused3,_name,_probe,_disable) \
+ static const char _name ## _text[] = _name_text; \
+ static inline int \
+ _name ## _probe ( struct nic *nic, void *hwdev ) { \
+ return _probe ( nic, hwdev ); \
+ } \
+ static inline void \
+ _name ## _disable ( struct nic *nic, void *hwdev ) { \
+ void ( * _unsafe_disable ) () = _disable; \
+ _unsafe_disable ( nic, hwdev ); \
+ } \
+ static inline int \
+ _name ## _pci_legacy_probe ( struct pci_device *pci, \
+ const struct pci_device_id *id __unused ) { \
+ return legacy_probe ( pci, legacy_pci_set_drvdata, \
+ &pci->dev, _name ## _probe, \
+ _name ## _disable ); \
+ } \
+ static inline void \
+ _name ## _pci_legacy_remove ( struct pci_device *pci ) { \
+ return legacy_remove ( pci, legacy_pci_get_drvdata, \
+ _name ## _disable ); \
+ } \
+ static inline int \
+ _name ## _isapnp_legacy_probe ( struct isapnp_device *isapnp, \
+ const struct isapnp_device_id *id __unused ) { \
+ return legacy_probe ( isapnp, legacy_isapnp_set_drvdata, \
+ &isapnp->dev, _name ## _probe, \
+ _name ## _disable ); \
+ } \
+ static inline void \
+ _name ## _isapnp_legacy_remove ( struct isapnp_device *isapnp ) { \
+ return legacy_remove ( isapnp, legacy_isapnp_get_drvdata, \
+ _name ## _disable ); \
+ } \
+ static inline int \
+ _name ## _eisa_legacy_probe ( struct eisa_device *eisa, \
+ const struct eisa_device_id *id __unused ) { \
+ return legacy_probe ( eisa, legacy_eisa_set_drvdata, \
+ &eisa->dev, _name ## _probe, \
+ _name ## _disable ); \
+ } \
+ static inline void \
+ _name ## _eisa_legacy_remove ( struct eisa_device *eisa ) { \
+ return legacy_remove ( eisa, legacy_eisa_get_drvdata, \
+ _name ## _disable ); \
+ } \
+ static inline int \
+ _name ## _mca_legacy_probe ( struct mca_device *mca, \
+ const struct mca_device_id *id __unused ) { \
+ return legacy_probe ( mca, legacy_mca_set_drvdata, \
+ &mca->dev, _name ## _probe, \
+ _name ## _disable ); \
+ } \
+ static inline void \
+ _name ## _mca_legacy_remove ( struct mca_device *mca ) { \
+ return legacy_remove ( mca, legacy_mca_get_drvdata, \
+ _name ## _disable ); \
+ } \
+ static inline int \
+ _name ## _isa_legacy_probe ( struct isa_device *isa ) { \
+ return legacy_probe ( isa, legacy_isa_set_drvdata, \
+ &isa->dev, _name ## _probe, \
+ _name ## _disable ); \
+ } \
+ static inline void \
+ _name ## _isa_legacy_remove ( struct isa_device *isa ) { \
+ return legacy_remove ( isa, legacy_isa_get_drvdata, \
+ _name ## _disable ); \
+ }
+
+#endif /* NIC_H */
diff --git a/gpxe/src/include/nmb.h b/gpxe/src/include/nmb.h
new file mode 100644
index 00000000..3e551ffd
--- /dev/null
+++ b/gpxe/src/include/nmb.h
@@ -0,0 +1,22 @@
+#ifndef NMB_H
+#define NMB_H
+
+#include <gpxe/dns.h>
+
+/*
+ * NetBIOS name query packets are basically the same as DNS packets,
+ * though the resource record format is different.
+ *
+ */
+
+#define DNS_TYPE_NB 0x20
+#define DNS_FLAG_BROADCAST ( 0x01 << 4 )
+#define NBNS_UDP_PORT 137
+
+struct dns_rr_info_nb {
+ struct dns_rr_info info;
+ uint16_t nb_flags;
+ struct in_addr nb_address;
+} __attribute__ (( packed ));
+
+#endif /* NMB_H */
diff --git a/gpxe/src/include/old_tcp.h b/gpxe/src/include/old_tcp.h
new file mode 100644
index 00000000..93e1485e
--- /dev/null
+++ b/gpxe/src/include/old_tcp.h
@@ -0,0 +1,37 @@
+#ifndef _TCP_H
+#define _TCP_H
+
+#define TCP_INITIAL_TIMEOUT (3*TICKS_PER_SEC)
+#define TCP_MAX_TIMEOUT (60*TICKS_PER_SEC)
+#define TCP_MIN_TIMEOUT (TICKS_PER_SEC)
+#define TCP_MAX_RETRY 10
+#define TCP_MAX_HEADER ((int)sizeof(struct iphdr)+64)
+#define TCP_MIN_WINDOW (1500-TCP_MAX_HEADER)
+#define TCP_MAX_WINDOW (65535-TCP_MAX_HEADER)
+
+#define FIN 1
+#define SYN 2
+#define RST 4
+#define PSH 8
+#define ACK 16
+#define URG 32
+
+
+struct tcphdr {
+ uint16_t src;
+ uint16_t dst;
+ int32_t seq;
+ int32_t ack;
+ uint16_t ctrl;
+ uint16_t window;
+ uint16_t chksum;
+ uint16_t urgent;
+};
+
+extern int tcp_transaction ( unsigned long destip, unsigned int destsock,
+ void *ptr,
+ int (*send)(int len, void *buf, void *ptr),
+ int (*recv)(int len, const void *buf, void *ptr));
+
+
+#endif /* _TCP_H */
diff --git a/gpxe/src/include/pc_kbd.h b/gpxe/src/include/pc_kbd.h
new file mode 100644
index 00000000..c125efa0
--- /dev/null
+++ b/gpxe/src/include/pc_kbd.h
@@ -0,0 +1,7 @@
+#ifndef _PC_KBD_H
+#define _PC_KBD_H
+
+int kbd_ischar(void);
+
+int kbd_getc(void);
+#endif
diff --git a/gpxe/src/include/pcmcia-opts.h b/gpxe/src/include/pcmcia-opts.h
new file mode 100644
index 00000000..70dc0921
--- /dev/null
+++ b/gpxe/src/include/pcmcia-opts.h
@@ -0,0 +1,23 @@
+// pcmcia-opts.h
+// special options file for development time. Later this could end in Config(?)
+#ifndef __pcmciaopts
+#define __pcmciaopts
+
+ #define _yes_ 1
+ #define _no_ 0
+
+ #define SUPPORT_I82365 (_yes_)
+// #define SUPPORT_YENTA (_no_)
+// #define SUPPORT_SOME_DRIVER (_no_)
+
+ #define PCMCIA_SHUTDOWN (_yes_)
+ #define MAP_ATTRMEM_TO 0xd0000
+ #define MAP_ATTRMEM_LEN 0x02000
+
+ #define PDEBUG 3
+ // The higher the more output you get, 0..3
+ // Not fully implemented though, but for the future...
+
+ #undef _yes_
+ #undef _no_
+#endif
diff --git a/gpxe/src/include/pcmcia.h b/gpxe/src/include/pcmcia.h
new file mode 100644
index 00000000..d528bea5
--- /dev/null
+++ b/gpxe/src/include/pcmcia.h
@@ -0,0 +1,156 @@
+// pcmcia.h - Header file for PCMCIA support
+
+#ifndef PCMCIA_H
+#define PCMCIA_H
+
+typedef unsigned char u_char;
+typedef unsigned short u_short;
+typedef unsigned int u_int;
+typedef unsigned long u_long;
+
+typedef u_short ioaddr_t;
+extern int sockets;
+
+#define MAXPCCSOCKS 8
+#define MAXPCCCONFIGS 8
+
+typedef enum ebpdriver_t { I82365, SOMEDRIVER } ebpdriver_t;
+typedef enum interface_func_t { INIT, SHUTDOWN, MAPATTRMEM, UNMAPATTRMEM, SELECTCONFIG } interface_func_t;
+typedef enum ebpstatus_t { EMPTY, HASCARD, INITIALIZED, SUSPENDED, OTHERDEVICE, UNKNOWN } ebpstatus_t;
+
+struct driver_interact_t {
+ ebpdriver_t id;
+ int (*f)(interface_func_t,int,int,int,int);
+ char *name;
+};
+struct pccsock_t {
+ ebpdriver_t device;
+ int drivernum;
+ ebpstatus_t status;
+ // Internal usage of the drivers:
+ int internalid;
+ int flags;
+ int ioaddr;
+ int type;
+ int configoffset;
+ int possibleconfignum;
+ int stringoffset;
+ u_int stringlength;
+ int rmask0;
+};
+
+extern struct pccsock_t pccsock[MAXPCCSOCKS];
+extern u_int pccsocks;
+
+struct pcc_config_t {
+ u_char index;
+ u_char irq;
+ int iowin;
+ int iolen;
+};
+
+
+int i82365_interfacer(interface_func_t,int,int,int,void *);
+void sleepticks(int);
+
+#define EINVAL 22
+
+
+//*********************************************************** cc.h:
+/* Definitions for card status flags for GetStatus */
+#define SS_WRPROT 0x0001
+#define SS_CARDLOCK 0x0002
+#define SS_EJECTION 0x0004
+#define SS_INSERTION 0x0008
+#define SS_BATDEAD 0x0010
+#define SS_BATWARN 0x0020
+#define SS_READY 0x0040
+#define SS_DETECT 0x0080
+#define SS_POWERON 0x0100
+#define SS_GPI 0x0200
+#define SS_STSCHG 0x0400
+#define SS_CARDBUS 0x0800
+#define SS_3VCARD 0x1000
+#define SS_XVCARD 0x2000
+#define SS_PENDING 0x4000
+
+/* cc.h: for InquireSocket */
+typedef struct socket_cap_t {
+ u_int features;
+ u_int irq_mask;
+ u_int map_size;
+ ioaddr_t io_offset;
+ u_char pci_irq;
+ //struct pci_dev *cb_dev;
+ //struct bus_operations *bus;
+ void *cb_dev;
+ void *bus;
+} socket_cap_t;
+/* InquireSocket capabilities */
+#define SS_CAP_PAGE_REGS 0x0001
+#define SS_CAP_VIRTUAL_BUS 0x0002
+#define SS_CAP_MEM_ALIGN 0x0004
+#define SS_CAP_STATIC_MAP 0x0008
+#define SS_CAP_PCCARD 0x4000
+#define SS_CAP_CARDBUS 0x8000
+
+/* for GetSocket, SetSocket */
+typedef struct socket_state_t {
+ u_int flags;
+ u_int csc_mask;
+ u_char Vcc, Vpp;
+ u_char io_irq;
+} socket_state_t;
+
+extern socket_state_t dead_socket;
+
+/* Socket configuration flags */
+#define SS_PWR_AUTO 0x0010
+#define SS_IOCARD 0x0020
+#define SS_RESET 0x0040
+#define SS_DMA_MODE 0x0080
+#define SS_SPKR_ENA 0x0100
+#define SS_OUTPUT_ENA 0x0200
+#define SS_DEBOUNCED 0x0400 /* Tell driver that the debounce delay has ended */
+#define SS_ZVCARD 0x0800
+
+/* Flags for I/O port and memory windows */
+#define MAP_ACTIVE 0x01
+#define MAP_16BIT 0x02
+#define MAP_AUTOSZ 0x04
+#define MAP_0WS 0x08
+#define MAP_WRPROT 0x10
+#define MAP_ATTRIB 0x20
+#define MAP_USE_WAIT 0x40
+#define MAP_PREFETCH 0x80
+
+/* Use this just for bridge windows */
+#define MAP_IOSPACE 0x20
+
+typedef struct pccard_io_map {
+ u_char map;
+ u_char flags;
+ u_short speed;
+ ioaddr_t start, stop;
+} pccard_io_map;
+
+
+typedef struct pccard_mem_map {
+ u_char map;
+ u_char flags;
+ u_short speed;
+ u_long sys_start, sys_stop;
+ u_int card_start;
+} pccard_mem_map;
+
+typedef struct cb_bridge_map {
+ u_char map;
+ u_char flags;
+ u_int start, stop;
+} cb_bridge_map;
+// need the global function pointer struct? *TODO*
+//************************************* end cc.h
+
+
+
+#endif /* PCMCIA_H */
diff --git a/gpxe/src/include/pxe.h b/gpxe/src/include/pxe.h
new file mode 100644
index 00000000..6d332ac7
--- /dev/null
+++ b/gpxe/src/include/pxe.h
@@ -0,0 +1,151 @@
+#ifndef PXE_H
+#define PXE_H
+
+#include "pxe_types.h"
+#include "pxe_api.h"
+#include <gpxe/device.h>
+
+/* Parameter block for pxenv_unknown() */
+struct s_PXENV_UNKNOWN {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} PACKED;
+
+typedef struct s_PXENV_UNKNOWN PXENV_UNKNOWN_t;
+
+/* Union used for PXE API calls; we don't know the type of the
+ * structure until we interpret the opcode. Also, Status is available
+ * in the same location for any opcode, and it's convenient to have
+ * non-specific access to it.
+ */
+union u_PXENV_ANY {
+ /* Make it easy to read status for any operation */
+ PXENV_STATUS_t Status;
+ struct s_PXENV_UNKNOWN unknown;
+ struct s_PXENV_UNLOAD_STACK unload_stack;
+ struct s_PXENV_GET_CACHED_INFO get_cached_info;
+ struct s_PXENV_TFTP_READ_FILE restart_tftp;
+ struct s_PXENV_START_UNDI start_undi;
+ struct s_PXENV_STOP_UNDI stop_undi;
+ struct s_PXENV_START_BASE start_base;
+ struct s_PXENV_STOP_BASE stop_base;
+ struct s_PXENV_TFTP_OPEN tftp_open;
+ struct s_PXENV_TFTP_CLOSE tftp_close;
+ struct s_PXENV_TFTP_READ tftp_read;
+ struct s_PXENV_TFTP_READ_FILE tftp_read_file;
+ struct s_PXENV_TFTP_GET_FSIZE tftp_get_fsize;
+ struct s_PXENV_UDP_OPEN udp_open;
+ struct s_PXENV_UDP_CLOSE udp_close;
+ struct s_PXENV_UDP_WRITE udp_write;
+ struct s_PXENV_UDP_READ udp_read;
+ struct s_PXENV_UNDI_STARTUP undi_startup;
+ struct s_PXENV_UNDI_CLEANUP undi_cleanup;
+ struct s_PXENV_UNDI_INITIALIZE undi_initialize;
+ struct s_PXENV_UNDI_RESET undi_reset_adapter;
+ struct s_PXENV_UNDI_SHUTDOWN undi_shutdown;
+ struct s_PXENV_UNDI_OPEN undi_open;
+ struct s_PXENV_UNDI_CLOSE undi_close;
+ struct s_PXENV_UNDI_TRANSMIT undi_transmit;
+ struct s_PXENV_UNDI_SET_MCAST_ADDRESS undi_set_mcast_address;
+ struct s_PXENV_UNDI_SET_STATION_ADDRESS undi_set_station_address;
+ struct s_PXENV_UNDI_SET_PACKET_FILTER undi_set_packet_filter;
+ struct s_PXENV_UNDI_GET_INFORMATION undi_get_information;
+ struct s_PXENV_UNDI_GET_STATISTICS undi_get_statistics;
+ struct s_PXENV_UNDI_CLEAR_STATISTICS undi_clear_statistics;
+ struct s_PXENV_UNDI_INITIATE_DIAGS undi_initiate_diags;
+ struct s_PXENV_UNDI_FORCE_INTERRUPT undi_force_interrupt;
+ struct s_PXENV_UNDI_GET_MCAST_ADDRESS undi_get_mcast_address;
+ struct s_PXENV_UNDI_GET_NIC_TYPE undi_get_nic_type;
+ struct s_PXENV_UNDI_GET_IFACE_INFO undi_get_iface_info;
+ struct s_PXENV_UNDI_GET_STATE undi_get_state;
+ struct s_PXENV_UNDI_ISR undi_isr;
+ struct s_PXENV_FILE_OPEN file_open;
+ struct s_PXENV_FILE_CLOSE file_close;
+ struct s_PXENV_FILE_SELECT file_select;
+ struct s_PXENV_FILE_READ file_read;
+ struct s_PXENV_GET_FILE_SIZE get_file_size;
+ struct s_PXENV_FILE_EXEC file_exec;
+ struct s_PXENV_FILE_API_CHECK file_api_check;
+};
+
+typedef union u_PXENV_ANY PXENV_ANY_t;
+
+/** An UNDI expansion ROM header */
+struct undi_rom_header {
+ /** Signature
+ *
+ * Must be equal to @c ROM_SIGNATURE
+ */
+ UINT16_t Signature;
+ /** ROM length in 512-byte blocks */
+ UINT8_t ROMLength;
+ /** Unused */
+ UINT8_t unused[0x13];
+ /** Offset of the PXE ROM ID structure */
+ UINT16_t PXEROMID;
+ /** Offset of the PCI ROM structure */
+ UINT16_t PCIRHeader;
+} PACKED;
+
+/** Signature for an expansion ROM */
+#define ROM_SIGNATURE 0xaa55
+
+/** An UNDI ROM ID structure */
+struct undi_rom_id {
+ /** Signature
+ *
+ * Must be equal to @c UNDI_ROM_ID_SIGNATURE
+ */
+ UINT32_t Signature;
+ /** Length of structure */
+ UINT8_t StructLength;
+ /** Checksum */
+ UINT8_t StructCksum;
+ /** Structure revision
+ *
+ * Must be zero.
+ */
+ UINT8_t StructRev;
+ /** UNDI revision
+ *
+ * Version 2.1.0 is encoded as the byte sequence 0x00, 0x01, 0x02.
+ */
+ UINT8_t UNDIRev[3];
+ /** Offset to UNDI loader */
+ UINT16_t UNDILoader;
+ /** Minimum required stack segment size */
+ UINT16_t StackSize;
+ /** Minimum required data segment size */
+ UINT16_t DataSize;
+ /** Minimum required code segment size */
+ UINT16_t CodeSize;
+} PACKED;
+
+/** Signature for an UNDI ROM ID structure */
+#define UNDI_ROM_ID_SIGNATURE \
+ ( ( 'U' << 0 ) + ( 'N' << 8 ) + ( 'D' << 16 ) + ( 'I' << 24 ) )
+
+/** A PCI expansion header */
+struct pcir_header {
+ /** Signature
+ *
+ * Must be equal to @c PCIR_SIGNATURE
+ */
+ uint32_t signature;
+ /** PCI vendor ID */
+ uint16_t vendor_id;
+ /** PCI device ID */
+ uint16_t device_id;
+} PACKED;
+
+/** Signature for an UNDI ROM ID structure */
+#define PCIR_SIGNATURE \
+ ( ( 'P' << 0 ) + ( 'C' << 8 ) + ( 'I' << 16 ) + ( 'R' << 24 ) )
+
+
+extern struct net_device *pxe_netdev;
+
+extern void pxe_set_netdev ( struct net_device *netdev );
+
+extern void pxe_set_cached_filename ( const unsigned char *filename );
+
+#endif /* PXE_H */
diff --git a/gpxe/src/include/pxe_api.h b/gpxe/src/include/pxe_api.h
new file mode 100644
index 00000000..b3d4bca8
--- /dev/null
+++ b/gpxe/src/include/pxe_api.h
@@ -0,0 +1,1841 @@
+#ifndef PXE_API_H
+#define PXE_API_H
+
+/*
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/** @file
+ *
+ * Preboot eXecution Environment (PXE) API
+ *
+ */
+
+#include "pxe_types.h"
+
+/** @addtogroup pxe Preboot eXecution Environment (PXE) API
+ * @{
+ */
+
+/** @defgroup pxe_api_call PXE entry points
+ *
+ * PXE entry points and calling conventions
+ *
+ * @{
+ */
+
+/** The PXENV+ structure */
+struct s_PXENV {
+ /** Signature
+ *
+ * Contains the bytes 'P', 'X', 'E', 'N', 'V', '+'.
+ */
+ UINT8_t Signature[6];
+ /** PXE API version
+ *
+ * MSB is major version number, LSB is minor version number.
+ * If the API version number is 0x0201 or greater, the !PXE
+ * structure pointed to by #PXEPtr should be used instead of
+ * this data structure.
+ */
+ UINT16_t Version;
+ UINT8_t Length; /**< Length of this structure */
+ /** Checksum
+ *
+ * The byte checksum of this structure (using the length in
+ * #Length) must be zero.
+ */
+ UINT8_t Checksum;
+ SEGOFF16_t RMEntry; /**< Real-mode PXENV+ entry point */
+ /** Protected-mode PXENV+ entry point offset
+ *
+ * PXE 2.1 deprecates this entry point. For protected-mode
+ * API calls, use the !PXE structure pointed to by #PXEPtr
+ * instead.
+ */
+ UINT32_t PMOffset;
+ /** Protected-mode PXENV+ entry point segment selector
+ *
+ * PXE 2.1 deprecates this entry point. For protected-mode
+ * API calls, use the !PXE structure pointed to by #PXEPtr
+ * instead.
+ */
+ SEGSEL_t PMSelector;
+ SEGSEL_t StackSeg; /**< Stack segment selector */
+ UINT16_t StackSize; /**< Stack segment size */
+ SEGSEL_t BC_CodeSeg; /**< Base-code code segment selector */
+ UINT16_t BC_CodeSize; /**< Base-code code segment size */
+ SEGSEL_t BC_DataSeg; /**< Base-code data segment selector */
+ UINT16_t BC_DataSize; /**< Base-code data segment size */
+ SEGSEL_t UNDIDataSeg; /**< UNDI data segment selector */
+ UINT16_t UNDIDataSize; /**< UNDI data segment size */
+ SEGSEL_t UNDICodeSeg; /**< UNDI code segment selector */
+ UINT16_t UNDICodeSize; /**< UNDI code segment size */
+ /** Address of the !PXE structure
+ *
+ * This field is present only if #Version is 0x0201 or
+ * greater. If present, it points to a struct s_PXE.
+ */
+ SEGOFF16_t PXEPtr;
+} PACKED;
+
+typedef struct s_PXENV PXENV_t;
+
+/** The !PXE structure */
+struct s_PXE {
+ /** Signature
+ *
+ * Contains the bytes '!', 'P', 'X', 'E'.
+ */
+ UINT8_t Signature[4];
+ UINT8_t StructLength; /**< Length of this structure */
+ /** Checksum
+ *
+ * The byte checksum of this structure (using the length in
+ * #StructLength) must be zero.
+ */
+ UINT8_t StructCksum;
+ /** Revision of this structure
+ *
+ * For PXE version 2.1, this field must be zero.
+ */
+ UINT8_t StructRev;
+ UINT8_t reserved_1; /**< Must be zero */
+ /** Address of the UNDI ROM ID structure
+ *
+ * This is a pointer to a struct s_UNDI_ROM_ID.
+ */
+ SEGOFF16_t UNDIROMID;
+ /** Address of the Base Code ROM ID structure
+ *
+ * This is a pointer to a struct s_BC_ROM_ID.
+ */
+ SEGOFF16_t BaseROMID;
+ /** 16-bit !PXE entry point
+ *
+ * This is the entry point for either real mode, or protected
+ * mode with a 16-bit stack segment.
+ */
+ SEGOFF16_t EntryPointSP;
+ /** 32-bit !PXE entry point
+ *
+ * This is the entry point for protected mode with a 32-bit
+ * stack segment.
+ */
+ SEGOFF16_t EntryPointESP;
+ /** Status call-out function
+ *
+ * @v 0 (if in a time-out loop)
+ * @v n Number of a received TFTP packet
+ * @ret 0 Continue operation
+ * @ret 1 Cancel operation
+ *
+ * This function will be called whenever the PXE stack is in
+ * protected mode, is waiting for an event (e.g. a DHCP reply)
+ * and wishes to allow the user to cancel the operation.
+ * Parameters are passed in register %ax; the return value
+ * must also be placed in register %ax. All other registers
+ * and flags @b must be preserved.
+ *
+ * In real mode, an internal function (that checks for a
+ * keypress) will be used.
+ *
+ * If this field is set to -1, no status call-out function
+ * will be used and consequently the user will not be allowed
+ * to interrupt operations.
+ *
+ * @note The PXE specification version 2.1 defines the
+ * StatusCallout field, mentions it 11 times, but nowhere
+ * defines what it actually does or how it gets called.
+ * Fortunately, the WfM specification version 1.1a deigns to
+ * inform us of such petty details.
+ */
+ SEGOFF16_t StatusCallout;
+ UINT8_t reserved_2; /**< Must be zero */
+ /** Number of segment descriptors
+ *
+ * If this number is greater than 7, the remaining descriptors
+ * follow immediately after #BC_CodeWrite.
+ */
+ UINT8_t SegDescCnt;
+ /** First protected-mode selector
+ *
+ * This is the segment selector value for the first segment
+ * assigned to PXE. Protected-mode selectors must be
+ * consecutive, according to the PXE 2.1 specification, though
+ * no reason is given. Each #SEGDESC_t includes a field for
+ * the segment selector, so this information is entirely
+ * redundant.
+ */
+ SEGSEL_t FirstSelector;
+ /** Stack segment descriptor */
+ SEGDESC_t Stack;
+ /** UNDI data segment descriptor */
+ SEGDESC_t UNDIData;
+ /** UNDI code segment descriptor */
+ SEGDESC_t UNDICode;
+ /** UNDI writable code segment descriptor */
+ SEGDESC_t UNDICodeWrite;
+ /** Base-code data segment descriptor */
+ SEGDESC_t BC_Data;
+ /** Base-code code segment descriptor */
+ SEGDESC_t BC_Code;
+ /** Base-code writable code segment descriptor */
+ SEGDESC_t BC_CodeWrite;
+} PACKED;
+
+typedef struct s_PXE PXE_t;
+
+/** @} */ /* pxe_api_call */
+
+/** @defgroup pxe_preboot_api PXE Preboot API
+ *
+ * General high-level functions: #PXENV_UNLOAD_STACK, #PXENV_START_UNDI etc.
+ *
+ * @{
+ */
+
+/** @defgroup pxenv_unload_stack PXENV_UNLOAD_STACK
+ *
+ * UNLOAD BASE CODE STACK
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_unload_stack() */
+#define PXENV_UNLOAD_STACK 0x0070
+
+/** Parameter block for pxenv_unload_stack() */
+struct s_PXENV_UNLOAD_STACK {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT8_t reserved[10]; /**< Must be zero */
+} PACKED;
+
+typedef struct s_PXENV_UNLOAD_STACK PXENV_UNLOAD_STACK_t;
+
+extern PXENV_EXIT_t pxenv_unload_stack ( struct s_PXENV_UNLOAD_STACK
+ *unload_stack );
+
+/** @} */ /* pxenv_unload_stack */
+
+/** @defgroup pxenv_get_cached_info PXENV_GET_CACHED_INFO
+ *
+ * GET CACHED INFO
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_get_cached_info() */
+#define PXENV_GET_CACHED_INFO 0x0071
+
+/** The client's DHCPDISCOVER packet */
+#define PXENV_PACKET_TYPE_DHCP_DISCOVER 1
+
+/** The DHCP server's DHCPACK packet */
+#define PXENV_PACKET_TYPE_DHCP_ACK 2
+
+/** The Boot Server's Discover Reply packet
+ *
+ * This packet contains DHCP option 60 set to "PXEClient", a valid
+ * boot file name, and may or may not contain MTFTP options.
+ */
+#define PXENV_PACKET_TYPE_CACHED_REPLY 3
+
+/** Parameter block for pxenv_get_cached_info() */
+struct s_PXENV_GET_CACHED_INFO {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** Packet type.
+ *
+ * Valid values are #PXENV_PACKET_TYPE_DHCP_DISCOVER,
+ * #PXENV_PACKET_TYPE_DHCP_ACK or #PXENV_PACKET_TYPE_CACHED_REPLY
+ */
+ UINT16_t PacketType;
+ UINT16_t BufferSize; /**< Buffer size */
+ SEGOFF16_t Buffer; /**< Buffer address */
+ UINT16_t BufferLimit; /**< Maximum buffer size */
+} PACKED;
+
+typedef struct s_PXENV_GET_CACHED_INFO PXENV_GET_CACHED_INFO_t;
+
+#define BOOTP_REQ 1 /**< A BOOTP request packet */
+#define BOOTP_REP 2 /**< A BOOTP reply packet */
+
+/** DHCP broadcast flag
+ *
+ * Request a broadcast response (DHCPOFFER or DHCPACK) from the DHCP
+ * server.
+ */
+#define BOOTP_BCAST 0x8000
+
+#define VM_RFC1048 0x63825363L /**< DHCP magic cookie */
+
+/** Maximum length of DHCP options */
+#define BOOTP_DHCPVEND 1024
+
+/** Format of buffer filled in by pxenv_get_cached_info()
+ *
+ * This somewhat convoluted data structure simply describes the layout
+ * of a DHCP packet. Refer to RFC2131 section 2 for a full
+ * description.
+ */
+struct bootph {
+ /** Message opcode.
+ *
+ * Valid values are #BOOTP_REQ and #BOOTP_REP.
+ */
+ UINT8_t opcode;
+ /** NIC hardware type.
+ *
+ * Valid values are as for s_PXENV_UNDI_GET_INFORMATION::HwType.
+ */
+ UINT8_t Hardware;
+ UINT8_t Hardlen; /**< MAC address length */
+ /** Gateway hops
+ *
+ * Zero in packets sent by the client. May be non-zero in
+ * replies from the DHCP server, if the reply comes via a DHCP
+ * relay agent.
+ */
+ UINT8_t Gatehops;
+ UINT32_t ident; /**< DHCP transaction id (xid) */
+ /** Elapsed time
+ *
+ * Number of seconds since the client began the DHCP
+ * transaction.
+ */
+ UINT16_t seconds;
+ /** Flags
+ *
+ * This is the bitwise-OR of any of the following values:
+ * #BOOTP_BCAST.
+ */
+ UINT16_t Flags;
+ /** Client IP address
+ *
+ * Set only if the client already has an IP address.
+ */
+ IP4_t cip;
+ /** Your IP address
+ *
+ * This is the IP address that the server assigns to the
+ * client.
+ */
+ IP4_t yip;
+ /** Server IP address
+ *
+ * This is the IP address of the BOOTP/DHCP server.
+ */
+ IP4_t sip;
+ /** Gateway IP address
+ *
+ * This is the IP address of the BOOTP/DHCP relay agent, if
+ * any. It is @b not (necessarily) the address of the default
+ * gateway for routing purposes.
+ */
+ IP4_t gip;
+ MAC_ADDR_t CAddr; /**< Client MAC address */
+ UINT8_t Sname[64]; /**< Server host name */
+ UINT8_t bootfile[128]; /**< Boot file name */
+ /** DHCP options
+ *
+ * Don't ask. Just laugh. Then burn a copy of the PXE
+ * specification and send Intel an e-mail asking them if
+ * they've figured out what a "union" does in C yet.
+ */
+ union bootph_vendor {
+ UINT8_t d[BOOTP_DHCPVEND]; /**< DHCP options */
+ /** DHCP options */
+ struct bootph_vendor_v {
+ /** DHCP magic cookie
+ *
+ * Should have the value #VM_RFC1048.
+ */
+ UINT8_t magic[4];
+ UINT32_t flags; /**< BOOTP flags/opcodes */
+ /** "End of BOOTP vendor extensions"
+ *
+ * Abandon hope, all ye who consider the
+ * purpose of this field.
+ */
+ UINT8_t pad[56];
+ } v;
+ } vendor;
+} PACKED;
+
+typedef struct bootph BOOTPLAYER_t;
+
+extern PXENV_EXIT_t pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO
+ *get_cached_info );
+
+/** @} */ /* pxenv_get_cached_info */
+
+/** @defgroup pxenv_restart_tftp PXENV_RESTART_TFTP
+ *
+ * RESTART TFTP
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_restart_tftp() */
+#define PXENV_RESTART_TFTP 0x0073
+
+/** Parameter block for pxenv_restart_tftp() */
+struct s_PXENV_TFTP_READ_FILE;
+
+typedef struct s_PXENV_RESTART_TFTP PXENV_RESTART_TFTP_t;
+
+extern PXENV_EXIT_t pxenv_restart_tftp ( struct s_PXENV_TFTP_READ_FILE
+ *restart_tftp );
+
+/** @} */ /* pxenv_restart_tftp */
+
+/** @defgroup pxenv_start_undi PXENV_START_UNDI
+ *
+ * START UNDI
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_start_undi() */
+#define PXENV_START_UNDI 0x0000
+
+/** Parameter block for pxenv_start_undi() */
+struct s_PXENV_START_UNDI {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** %ax register as passed to the Option ROM initialisation routine.
+ *
+ * For a PCI device, this should contain the bus:dev:fn value
+ * that uniquely identifies the PCI device in the system. For
+ * a non-PCI device, this field is not defined.
+ */
+ UINT16_t AX;
+ /** %bx register as passed to the Option ROM initialisation routine.
+ *
+ * For an ISAPnP device, this should contain the Card Select
+ * Number assigned to the ISAPnP card. For non-ISAPnP
+ * devices, this should contain 0xffff.
+ */
+ UINT16_t BX;
+ /** %dx register as passed to the Option ROM initialisation routine.
+ *
+ * For an ISAPnP device, this should contain the ISAPnP Read
+ * Port address as currently set in all ISAPnP cards. If
+ * there are no ISAPnP cards, this should contain 0xffff. (If
+ * this is a non-ISAPnP device, but there are ISAPnP cards in
+ * the system, this value is not well defined.)
+ */
+ UINT16_t DX;
+ /** %di register as passed to the Option ROM initialisation routine.
+ *
+ * This contains the #OFF16_t portion of a struct #s_SEGOFF16
+ * that points to the System BIOS Plug and Play Installation
+ * Check Structure. (Refer to section 4.4 of the Plug and
+ * Play BIOS specification for a description of this
+ * structure.)
+ *
+ * @note The PXE specification defines the type of this field
+ * as #UINT16_t. For x86, #OFF16_t and #UINT16_t are
+ * equivalent anyway; for other architectures #OFF16_t makes
+ * more sense.
+ */
+ OFF16_t DI;
+ /** %es register as passed to the Option ROM initialisation routine.
+ *
+ * This contains the #SEGSEL_t portion of a struct #s_SEGOFF16
+ * that points to the System BIOS Plug and Play Installation
+ * Check Structure. (Refer to section 4.4 of the Plug and
+ * Play BIOS specification for a description of this
+ * structure.)
+ *
+ * @note The PXE specification defines the type of this field
+ * as #UINT16_t. For x86, #SEGSEL_t and #UINT16_t are
+ * equivalent anyway; for other architectures #SEGSEL_t makes
+ * more sense.
+ */
+ SEGSEL_t ES;
+} PACKED;
+
+typedef struct s_PXENV_START_UNDI PXENV_START_UNDI_t;
+
+extern PXENV_EXIT_t pxenv_start_undi ( struct s_PXENV_START_UNDI *start_undi );
+
+/** @} */ /* pxenv_start_undi */
+
+/** @defgroup pxenv_stop_undi PXENV_STOP_UNDI
+ *
+ * STOP UNDI
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_stop_undi() */
+#define PXENV_STOP_UNDI 0x0015
+
+/** Parameter block for pxenv_stop_undi() */
+struct s_PXENV_STOP_UNDI {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} PACKED;
+
+typedef struct s_PXENV_STOP_UNDI PXENV_STOP_UNDI_t;
+
+extern PXENV_EXIT_t pxenv_stop_undi ( struct s_PXENV_STOP_UNDI *stop_undi );
+
+/** @} */ /* pxenv_stop_undi */
+
+/** @defgroup pxenv_start_base PXENV_START_BASE
+ *
+ * START BASE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_start_base() */
+#define PXENV_START_BASE 0x0075
+
+/** Parameter block for pxenv_start_base() */
+struct s_PXENV_START_BASE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} PACKED;
+
+typedef struct s_PXENV_START_BASE PXENV_START_BASE_t;
+
+extern PXENV_EXIT_t pxenv_start_base ( struct s_PXENV_START_BASE *start_base );
+
+/** @} */ /* pxenv_start_base */
+
+/** @defgroup pxenv_stop_base PXENV_STOP_BASE
+ *
+ * STOP BASE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_stop_base() */
+#define PXENV_STOP_BASE 0x0076
+
+/** Parameter block for pxenv_stop_base() */
+struct s_PXENV_STOP_BASE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} PACKED;
+
+typedef struct s_PXENV_STOP_BASE PXENV_STOP_BASE_t;
+
+extern PXENV_EXIT_t pxenv_stop_base ( struct s_PXENV_STOP_BASE *stop_base );
+
+/** @} */ /* pxenv_stop_base */
+
+/** @} */ /* pxe_preboot_api */
+
+/** @defgroup pxe_tftp_api PXE TFTP API
+ *
+ * Download files via TFTP or MTFTP
+ *
+ * @{
+ */
+
+/** @defgroup pxenv_tftp_open PXENV_TFTP_OPEN
+ *
+ * TFTP OPEN
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_tftp_open() */
+#define PXENV_TFTP_OPEN 0x0020
+
+/** Parameter block for pxenv_tftp_open() */
+struct s_PXENV_TFTP_OPEN {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ IP4_t ServerIPAddress; /**< TFTP server IP address */
+ IP4_t GatewayIPAddress; /**< Relay agent IP address */
+ UINT8_t FileName[128]; /**< File name */
+ UDP_PORT_t TFTPPort; /**< TFTP server UDP port */
+ /** Requested size of TFTP packets
+ *
+ * This is the TFTP "blksize" option. This must be at least
+ * 512, since servers that do not support TFTP options cannot
+ * negotiate blocksizes smaller than this.
+ */
+ UINT16_t PacketSize;
+} PACKED;
+
+typedef struct s_PXENV_TFTP_OPEN PXENV_TFTP_OPEN_t;
+
+extern PXENV_EXIT_t pxenv_tftp_open ( struct s_PXENV_TFTP_OPEN *tftp_open );
+
+/** @} */ /* pxenv_tftp_open */
+
+/** @defgroup pxenv_tftp_close PXENV_TFTP_CLOSE
+ *
+ * TFTP CLOSE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_tftp_close() */
+#define PXENV_TFTP_CLOSE 0x0021
+
+/** Parameter block for pxenv_tftp_close() */
+struct s_PXENV_TFTP_CLOSE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} PACKED;
+
+typedef struct s_PXENV_TFTP_CLOSE PXENV_TFTP_CLOSE_t;
+
+extern PXENV_EXIT_t pxenv_tftp_close ( struct s_PXENV_TFTP_CLOSE *tftp_close );
+
+/** @} */ /* pxenv_tftp_close */
+
+/** @defgroup pxenv_tftp_read PXENV_TFTP_READ
+ *
+ * TFTP READ
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_tftp_read() */
+#define PXENV_TFTP_READ 0x0022
+
+/** Parameter block for pxenv_tftp_read() */
+struct s_PXENV_TFTP_READ {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT16_t PacketNumber; /**< TFTP packet number */
+ UINT16_t BufferSize; /**< Size of data buffer */
+ SEGOFF16_t Buffer; /**< Address of data buffer */
+} PACKED;
+
+typedef struct s_PXENV_TFTP_READ PXENV_TFTP_READ_t;
+
+extern PXENV_EXIT_t pxenv_tftp_read ( struct s_PXENV_TFTP_READ *tftp_read );
+
+/** @} */ /* pxenv_tftp_read */
+
+/** @defgroup pxenv_tftp_read_file PXENV_TFTP_READ_FILE
+ *
+ * TFTP/MTFTP READ FILE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_tftp_read_file() */
+#define PXENV_TFTP_READ_FILE 0x0023
+
+/** Parameter block for pxenv_tftp_read_file() */
+struct s_PXENV_TFTP_READ_FILE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT8_t FileName[128]; /**< File name */
+ UINT32_t BufferSize; /**< Size of data buffer */
+ ADDR32_t Buffer; /**< Address of data buffer */
+ IP4_t ServerIPAddress; /**< TFTP server IP address */
+ IP4_t GatewayIPAddress; /**< Relay agent IP address */
+ /** File multicast IP address */
+ IP4_t McastIPAddress;
+ /** Client multicast listening port */
+ UDP_PORT_t TFTPClntPort;
+ /** Server multicast listening port */
+ UDP_PORT_t TFTPSrvPort;
+ /** TFTP open timeout.
+ *
+ * This is the timeout for receiving the first DATA or ACK
+ * packets during the MTFTP Listen phase.
+ */
+ UINT16_t TFTPOpenTimeOut;
+ /** TFTP reopen timeout.
+ *
+ * This is the timeout for receiving an ACK packet while in
+ * the MTFTP Listen phase (when at least one ACK packet has
+ * already been seen).
+ */
+ UINT16_t TFTPReopenDelay;
+} PACKED;
+
+typedef struct s_PXENV_TFTP_READ_FILE PXENV_TFTP_READ_FILE_t;
+
+extern PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE
+ *tftp_read_file );
+
+/** @} */ /* pxenv_tftp_read_file */
+
+/** @defgroup pxenv_tftp_get_fsize PXENV_TFTP_GET_FSIZE
+ *
+ * TFTP GET FILE SIZE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_tftp_get_fsize() */
+#define PXENV_TFTP_GET_FSIZE 0x0025
+
+/** Parameter block for pxenv_tftp_get_fsize() */
+struct s_PXENV_TFTP_GET_FSIZE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ IP4_t ServerIPAddress; /**< TFTP server IP address */
+ IP4_t GatewayIPAddress; /**< Relay agent IP address */
+ UINT8_t FileName[128]; /**< File name */
+ UINT32_t FileSize; /**< Size of the file */
+} PACKED;
+
+typedef struct s_PXENV_TFTP_GET_FSIZE PXENV_TFTP_GET_FSIZE_t;
+
+extern PXENV_EXIT_t pxenv_tftp_get_fsize ( struct s_PXENV_TFTP_GET_FSIZE
+ *get_fsize );
+
+/** @} */ /* pxenv_tftp_get_fsize */
+
+/** @} */ /* pxe_tftp_api */
+
+/** @defgroup pxe_udp_api PXE UDP API
+ *
+ * Transmit and receive UDP packets
+ *
+ * @{
+ */
+
+/** @defgroup pxenv_udp_open PXENV_UDP_OPEN
+ *
+ * UDP OPEN
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_udp_open() */
+#define PXENV_UDP_OPEN 0x0030
+
+/** Parameter block for pxenv_udp_open() */
+struct s_PXENV_UDP_OPEN {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ IP4_t src_ip; /**< IP address of this station */
+} PACKED;
+
+typedef struct s_PXENV_UDP_OPEN PXENV_UDP_OPEN_t;
+
+extern PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *udp_open );
+
+/** @} */ /* pxenv_udp_open */
+
+/** @defgroup pxenv_udp_close PXENV_UDP_CLOSE
+ *
+ * UDP CLOSE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_udp_close() */
+#define PXENV_UDP_CLOSE 0x0031
+
+/** Parameter block for pxenv_udp_close() */
+struct s_PXENV_UDP_CLOSE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} PACKED;
+
+typedef struct s_PXENV_UDP_CLOSE PXENV_UDP_CLOSE_t;
+
+extern PXENV_EXIT_t pxenv_udp_close ( struct s_PXENV_UDP_CLOSE *udp_close );
+
+/** @} */ /* pxenv_udp_close */
+
+/** @defgroup pxenv_udp_write PXENV_UDP_WRITE
+ *
+ * UDP WRITE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_udp_write() */
+#define PXENV_UDP_WRITE 0x0033
+
+/** Parameter block for pxenv_udp_write() */
+struct s_PXENV_UDP_WRITE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ IP4_t ip; /**< Destination IP address */
+ IP4_t gw; /**< Relay agent IP address */
+ UDP_PORT_t src_port; /**< Source UDP port */
+ UDP_PORT_t dst_port; /**< Destination UDP port */
+ UINT16_t buffer_size; /**< UDP payload buffer size */
+ SEGOFF16_t buffer; /**< UDP payload buffer address */
+} PACKED;
+
+typedef struct s_PXENV_UDP_WRITE PXENV_UDP_WRITE_t;
+
+extern PXENV_EXIT_t pxenv_udp_write ( struct s_PXENV_UDP_WRITE *udp_write );
+
+/** @} */ /* pxenv_udp_write */
+
+/** @defgroup pxenv_udp_read PXENV_UDP_READ
+ *
+ * UDP READ
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_udp_read() */
+#define PXENV_UDP_READ 0x0032
+
+/** Parameter block for pxenv_udp_read() */
+struct s_PXENV_UDP_READ {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ IP4_t src_ip; /**< Source IP address */
+ IP4_t dest_ip; /**< Destination IP address */
+ UDP_PORT_t s_port; /**< Source UDP port */
+ UDP_PORT_t d_port; /**< Destination UDP port */
+ UINT16_t buffer_size; /**< UDP payload buffer size */
+ SEGOFF16_t buffer; /**< UDP payload buffer address */
+} PACKED;
+
+typedef struct s_PXENV_UDP_READ PXENV_UDP_READ_t;
+
+extern PXENV_EXIT_t pxenv_udp_read ( struct s_PXENV_UDP_READ *udp_read );
+
+/** @} */ /* pxenv_udp_read */
+
+/** @} */ /* pxe_udp_api */
+
+/** @defgroup pxe_undi_api PXE UNDI API
+ *
+ * Direct control of the network interface card
+ *
+ * @{
+ */
+
+/** @defgroup pxenv_undi_startup PXENV_UNDI_STARTUP
+ *
+ * UNDI STARTUP
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_startup() */
+#define PXENV_UNDI_STARTUP 0x0001
+
+#define PXENV_BUS_ISA 0 /**< ISA bus type */
+#define PXENV_BUS_EISA 1 /**< EISA bus type */
+#define PXENV_BUS_MCA 2 /**< MCA bus type */
+#define PXENV_BUS_PCI 3 /**< PCI bus type */
+#define PXENV_BUS_VESA 4 /**< VESA bus type */
+#define PXENV_BUS_PCMCIA 5 /**< PCMCIA bus type */
+
+/** Parameter block for pxenv_undi_startup() */
+struct s_PXENV_UNDI_STARTUP {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} PACKED;
+
+typedef struct s_PXENV_UNDI_STARTUP PXENV_UNDI_STARTUP_t;
+
+extern PXENV_EXIT_t pxenv_undi_startup ( struct s_PXENV_UNDI_STARTUP
+ *undi_startup );
+
+/** @} */ /* pxenv_undi_startup */
+
+/** @defgroup pxenv_undi_cleanup PXENV_UNDI_CLEANUP
+ *
+ * UNDI CLEANUP
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_cleanup() */
+#define PXENV_UNDI_CLEANUP 0x0002
+
+/** Parameter block for pxenv_undi_cleanup() */
+struct s_PXENV_UNDI_CLEANUP {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} PACKED;
+
+typedef struct s_PXENV_UNDI_CLEANUP PXENV_UNDI_CLEANUP_t;
+
+extern PXENV_EXIT_t pxenv_undi_cleanup ( struct s_PXENV_UNDI_CLEANUP
+ *undi_cleanup );
+
+/** @} */ /* pxenv_undi_cleanup */
+
+/** @defgroup pxenv_undi_initialize PXENV_UNDI_INITIALIZE
+ *
+ * UNDI INITIALIZE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_initialize() */
+#define PXENV_UNDI_INITIALIZE 0x0003
+
+/** Parameter block for pxenv_undi_initialize() */
+struct s_PXENV_UNDI_INITIALIZE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** NDIS 2.0 configuration information, or NULL
+ *
+ * This is a pointer to the data structure returned by the
+ * NDIS 2.0 GetProtocolManagerInfo() API call. The data
+ * structure is documented, in a rather haphazard way, in
+ * section 4-17 of the NDIS 2.0 specification.
+ */
+ ADDR32_t ProtocolIni;
+ UINT8_t reserved[8]; /**< Must be zero */
+} PACKED;
+
+typedef struct s_PXENV_UNDI_INITIALIZE PXENV_UNDI_INITIALIZE_t;
+
+extern PXENV_EXIT_t pxenv_undi_initialize ( struct s_PXENV_UNDI_INITIALIZE
+ *undi_initialize );
+
+/** @} */ /* pxenv_undi_initialize */
+
+/** @defgroup pxenv_undi_reset_adapter PXENV_UNDI_RESET_ADAPTER
+ *
+ * UNDI RESET ADAPTER
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_reset_adapter() */
+#define PXENV_UNDI_RESET_ADAPTER 0x0004
+
+/** Maximum number of multicast MAC addresses */
+#define MAXNUM_MCADDR 8
+
+/** List of multicast MAC addresses */
+struct s_PXENV_UNDI_MCAST_ADDRESS {
+ /** Number of multicast MAC addresses */
+ UINT16_t MCastAddrCount;
+ /** List of up to #MAXNUM_MCADDR multicast MAC addresses */
+ MAC_ADDR_t McastAddr[MAXNUM_MCADDR];
+} PACKED;
+
+typedef struct s_PXENV_UNDI_MCAST_ADDRESS PXENV_UNDI_MCAST_ADDRESS_t;
+
+/** Parameter block for pxenv_undi_reset_adapter() */
+struct s_PXENV_UNDI_RESET {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** Multicast MAC addresses */
+ struct s_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
+} PACKED;
+
+typedef struct s_PXENV_UNDI_RESET PXENV_UNDI_RESET_t;
+
+extern PXENV_EXIT_t pxenv_undi_reset_adapter ( struct s_PXENV_UNDI_RESET
+ *undi_reset_adapter );
+
+/** @} */ /* pxenv_undi_reset_adapter */
+
+/** @defgroup pxenv_undi_shutdown PXENV_UNDI_SHUTDOWN
+ *
+ * UNDI SHUTDOWN
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_shutdown() */
+#define PXENV_UNDI_SHUTDOWN 0x0005
+
+/** Parameter block for pxenv_undi_shutdown() */
+struct s_PXENV_UNDI_SHUTDOWN {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} PACKED;
+
+typedef struct s_PXENV_UNDI_SHUTDOWN PXENV_UNDI_SHUTDOWN_t;
+
+extern PXENV_EXIT_t pxenv_undi_shutdown ( struct s_PXENV_UNDI_SHUTDOWN
+ *undi_shutdown );
+
+/** @} */ /* pxenv_undi_shutdown */
+
+/** @defgroup pxenv_undi_open PXENV_UNDI_OPEN
+ *
+ * UNDI OPEN
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_open() */
+#define PXENV_UNDI_OPEN 0x0006
+
+/** Accept "directed" packets
+ *
+ * These are packets addresses to either this adapter's MAC address or
+ * to any of the configured multicast MAC addresses (see
+ * #s_PXENV_UNDI_MCAST_ADDRESS).
+ */
+#define FLTR_DIRECTED 0x0001
+/** Accept broadcast packets */
+#define FLTR_BRDCST 0x0002
+/** Accept all packets; listen in promiscuous mode */
+#define FLTR_PRMSCS 0x0004
+/** Accept source-routed packets */
+#define FLTR_SRC_RTG 0x0008
+
+/** Parameter block for pxenv_undi_open() */
+struct s_PXENV_UNDI_OPEN {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** Open flags as defined in NDIS 2.0
+ *
+ * This is the OpenOptions field as passed to the NDIS 2.0
+ * OpenAdapter() API call. It is defined to be "adapter
+ * specific", though 0 is guaranteed to be a valid value.
+ */
+ UINT16_t OpenFlag;
+ /** Receive packet filter
+ *
+ * This is the bitwise-OR of any of the following flags:
+ * #FLTR_DIRECTED, #FLTR_BRDCST, #FLTR_PRMSCS and
+ * #FLTR_SRC_RTG.
+ */
+ UINT16_t PktFilter;
+ /** Multicast MAC addresses */
+ struct s_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
+} PACKED;
+
+typedef struct s_PXENV_UNDI_OPEN PXENV_UNDI_OPEN_t;
+
+extern PXENV_EXIT_t pxenv_undi_open ( struct s_PXENV_UNDI_OPEN *undi_open );
+
+/** @} */ /* pxenv_undi_open */
+
+/** @defgroup pxenv_undi_close PXENV_UNDI_CLOSE
+ *
+ * UNDI CLOSE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_close() */
+#define PXENV_UNDI_CLOSE 0x0007
+
+/** Parameter block for pxenv_undi_close() */
+struct s_PXENV_UNDI_CLOSE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} PACKED;
+
+typedef struct s_PXENV_UNDI_CLOSE PXENV_UNDI_CLOSE_t;
+
+extern PXENV_EXIT_t pxenv_undi_close ( struct s_PXENV_UNDI_CLOSE *undi_close );
+
+/** @} */ /* pxenv_undi_close */
+
+/** @defgroup pxenv_undi_transmit PXENV_UNDI_TRANSMIT
+ *
+ * UNDI TRANSMIT PACKET
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_transmit() */
+#define PXENV_UNDI_TRANSMIT 0x0008
+
+#define P_UNKNOWN 0 /**< Media header already filled in */
+#define P_IP 1 /**< IP protocol */
+#define P_ARP 2 /**< ARP protocol */
+#define P_RARP 3 /**< RARP protocol */
+#define P_OTHER 4 /**< Other protocol */
+
+#define XMT_DESTADDR 0x0000 /**< Unicast packet */
+#define XMT_BROADCAST 0x0001 /**< Broadcast packet */
+
+/** Maximum number of data blocks in a transmit buffer descriptor */
+#define MAX_DATA_BLKS 8
+
+/** A transmit buffer descriptor, as pointed to by s_PXENV_UNDI_TRANSMIT::TBD
+ */
+struct s_PXENV_UNDI_TBD {
+ UINT16_t ImmedLength; /**< Length of the transmit buffer */
+ SEGOFF16_t Xmit; /**< Address of the transmit buffer */
+ UINT16_t DataBlkCount;
+ /** Array of up to #MAX_DATA_BLKS additional transmit buffers */
+ struct DataBlk {
+ /** Always 1
+ *
+ * A value of 0 would indicate that #TDDataPtr were an
+ * #ADDR32_t rather than a #SEGOFF16_t. The PXE
+ * specification version 2.1 explicitly states that
+ * this is not supported; #TDDataPtr will always be a
+ * #SEGOFF16_t.
+ */
+ UINT8_t TDPtrType;
+ UINT8_t TDRsvdByte; /**< Must be zero */
+ UINT16_t TDDataLen; /**< Length of this transmit buffer */
+ SEGOFF16_t TDDataPtr; /**< Address of this transmit buffer */
+ } DataBlock[MAX_DATA_BLKS];
+} PACKED;
+
+typedef struct s_PXENV_UNDI_TBD PXENV_UNDI_TBD_t;
+
+/** Parameter block for pxenv_undi_transmit() */
+struct s_PXENV_UNDI_TRANSMIT {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** Protocol
+ *
+ * Valid values are #P_UNKNOWN, #P_IP, #P_ARP or #P_RARP. If
+ * the caller has already filled in the media header, this
+ * field must be set to #P_UNKNOWN.
+ */
+ UINT8_t Protocol;
+ /** Unicast/broadcast flag
+ *
+ * Valid values are #XMT_DESTADDR or #XMT_BROADCAST.
+ */
+ UINT8_t XmitFlag;
+ SEGOFF16_t DestAddr; /**< Destination MAC address */
+ /** Address of the Transmit Buffer Descriptor
+ *
+ * This is a pointer to a struct s_PXENV_UNDI_TBD.
+ */
+ SEGOFF16_t TBD;
+ UINT32_t Reserved[2]; /**< Must be zero */
+} PACKED;
+
+typedef struct s_PXENV_UNDI_TRANSMIT PXENV_UNDI_TRANSMIT_t;
+
+extern PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT
+ *undi_transmit );
+
+/** @} */ /* pxenv_undi_transmit */
+
+/** @defgroup pxenv_undi_set_mcast_address PXENV_UNDI_SET_MCAST_ADDRESS
+ *
+ * UNDI SET MULTICAST ADDRESS
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_set_mcast_address() */
+#define PXENV_UNDI_SET_MCAST_ADDRESS 0x0009
+
+/** Parameter block for pxenv_undi_set_mcast_address() */
+struct s_PXENV_UNDI_SET_MCAST_ADDRESS {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** List of multicast addresses */
+ struct s_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
+} PACKED;
+
+typedef struct s_PXENV_UNDI_SET_MCAST_ADDRESS PXENV_UNDI_SET_MCAST_ADDRESS_t;
+
+extern PXENV_EXIT_t pxenv_undi_set_mcast_address (
+ struct s_PXENV_UNDI_SET_MCAST_ADDRESS *undi_set_mcast_address );
+
+/** @} */ /* pxenv_undi_set_mcast_address */
+
+/** @defgroup pxenv_undi_set_station_address PXENV_UNDI_SET_STATION_ADDRESS
+ *
+ * UNDI SET STATION ADDRESS
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_set_station_address() */
+#define PXENV_UNDI_SET_STATION_ADDRESS 0x000a
+
+/** Parameter block for pxenv_undi_set_station_address() */
+struct s_PXENV_UNDI_SET_STATION_ADDRESS {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ MAC_ADDR_t StationAddress; /**< Station MAC address */
+} PACKED;
+
+typedef struct s_PXENV_UNDI_SET_STATION_ADDRESS PXENV_UNDI_SET_STATION_ADDRESS_t;
+
+extern PXENV_EXIT_t pxenv_undi_set_station_address (
+ struct s_PXENV_UNDI_SET_STATION_ADDRESS *undi_set_station_address );
+
+/** @} */ /* pxenv_undi_set_station_address */
+
+/** @defgroup pxenv_undi_set_packet_filter PXENV_UNDI_SET_PACKET_FILTER
+ *
+ * UNDI SET PACKET FILTER
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_set_packet_filter() */
+#define PXENV_UNDI_SET_PACKET_FILTER 0x000b
+
+/** Parameter block for pxenv_undi_set_packet_filter() */
+struct s_PXENV_UNDI_SET_PACKET_FILTER {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** Receive packet filter
+ *
+ * This field takes the same values as
+ * s_PXENV_UNDI_OPEN::PktFilter.
+ *
+ * @note Yes, this field is a different size to
+ * s_PXENV_UNDI_OPEN::PktFilter. Blame "the managers at Intel
+ * who apparently let a consultant come up with the spec
+ * without any kind of adult supervision" (quote from hpa).
+ */
+ UINT8_t filter;
+} PACKED;
+
+typedef struct s_PXENV_UNDI_SET_PACKET_FILTER PXENV_UNDI_SET_PACKET_FILTER_t;
+
+extern PXENV_EXIT_t pxenv_undi_set_packet_filter (
+ struct s_PXENV_UNDI_SET_PACKET_FILTER *undi_set_packet_filter );
+
+/** @} */ /* pxenv_undi_set_packet_filter */
+
+/** @defgroup pxenv_undi_get_information PXENV_UNDI_GET_INFORMATION
+ *
+ * UNDI GET INFORMATION
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_get_information() */
+#define PXENV_UNDI_GET_INFORMATION 0x000c
+
+#define ETHER_TYPE 1 /**< Ethernet (10Mb) */
+#define EXP_ETHER_TYPE 2 /**< Experimental Ethernet (3Mb) */
+#define AX25_TYPE 3 /**< Amateur Radio AX.25 */
+#define TOKEN_RING_TYPE 4 /**< Proteon ProNET Token Ring */
+#define CHAOS_TYPE 5 /**< Chaos */
+#define IEEE_TYPE 6 /**< IEEE 802 Networks */
+#define ARCNET_TYPE 7 /**< ARCNET */
+
+/** Parameter block for pxenv_undi_get_information() */
+struct s_PXENV_UNDI_GET_INFORMATION {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT16_t BaseIo; /**< I/O base address */
+ UINT16_t IntNumber; /**< IRQ number */
+ UINT16_t MaxTranUnit; /**< Adapter MTU */
+ /** Hardware type
+ *
+ * Valid values are defined in RFC1010 ("Assigned numbers"),
+ * and are #ETHER_TYPE, #EXP_ETHER_TYPE, #AX25_TYPE,
+ * #TOKEN_RING_TYPE, #CHAOS_TYPE, #IEEE_TYPE or #ARCNET_TYPE.
+ */
+ UINT16_t HwType;
+ UINT16_t HwAddrLen; /**< MAC address length */
+ MAC_ADDR_t CurrentNodeAddress; /**< Current MAC address */
+ MAC_ADDR_t PermNodeAddress; /**< Permanent (EEPROM) MAC address */
+ SEGSEL_t ROMAddress; /**< Real-mode ROM segment address */
+ UINT16_t RxBufCt; /**< Receive queue length */
+ UINT16_t TxBufCt; /**< Transmit queue length */
+} PACKED;
+
+typedef struct s_PXENV_UNDI_GET_INFORMATION PXENV_UNDI_GET_INFORMATION_t;
+
+extern PXENV_EXIT_t pxenv_undi_get_information (
+ struct s_PXENV_UNDI_GET_INFORMATION *undi_get_information );
+
+/** @} */ /* pxenv_undi_get_information */
+
+/** @defgroup pxenv_undi_get_statistics PXENV_UNDI_GET_STATISTICS
+ *
+ * UNDI GET STATISTICS
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_get_statistics() */
+#define PXENV_UNDI_GET_STATISTICS 0x000d
+
+/** Parameter block for pxenv_undi_get_statistics() */
+struct s_PXENV_UNDI_GET_STATISTICS {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT32_t XmtGoodFrames; /**< Successful transmission count */
+ UINT32_t RcvGoodFrames; /**< Successful reception count */
+ UINT32_t RcvCRCErrors; /**< Receive CRC error count */
+ UINT32_t RcvResourceErrors; /**< Receive queue overflow count */
+} PACKED;
+
+typedef struct s_PXENV_UNDI_GET_STATISTICS PXENV_UNDI_GET_STATISTICS_t;
+
+extern PXENV_EXIT_t pxenv_undi_get_statistics (
+ struct s_PXENV_UNDI_GET_STATISTICS *undi_get_statistics );
+
+/** @} */ /* pxenv_undi_get_statistics */
+
+/** @defgroup pxenv_undi_clear_statistics PXENV_UNDI_CLEAR_STATISTICS
+ *
+ * UNDI CLEAR STATISTICS
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_clear_statistics() */
+#define PXENV_UNDI_CLEAR_STATISTICS 0x000e
+
+/** Parameter block for pxenv_undi_clear_statistics() */
+struct s_PXENV_UNDI_CLEAR_STATISTICS {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} PACKED;
+
+typedef struct s_PXENV_UNDI_CLEAR_STATISTICS PXENV_UNDI_CLEAR_STATISTICS_t;
+
+extern PXENV_EXIT_t pxenv_undi_clear_statistics (
+ struct s_PXENV_UNDI_CLEAR_STATISTICS *undi_clear_statistics );
+
+/** @} */ /* pxenv_undi_clear_statistics */
+
+/** @defgroup pxenv_undi_initiate_diags PXENV_UNDI_INITIATE_DIAGS
+ *
+ * UNDI INITIATE DIAGS
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_initiate_diags() */
+#define PXENV_UNDI_INITIATE_DIAGS 0x000f
+
+/** Parameter block for pxenv_undi_initiate_diags() */
+struct s_PXENV_UNDI_INITIATE_DIAGS {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} PACKED;
+
+typedef struct s_PXENV_UNDI_INITIATE_DIAGS PXENV_UNDI_INITIATE_DIAGS_t;
+
+extern PXENV_EXIT_t pxenv_undi_initiate_diags (
+ struct s_PXENV_UNDI_INITIATE_DIAGS *undi_initiate_diags );
+
+/** @} */ /* pxenv_undi_initiate_diags */
+
+/** @defgroup pxenv_undi_force_interrupt PXENV_UNDI_FORCE_INTERRUPT
+ *
+ * UNDI FORCE INTERRUPT
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_force_interrupt() */
+#define PXENV_UNDI_FORCE_INTERRUPT 0x0010
+
+/** Parameter block for pxenv_undi_force_interrupt() */
+struct s_PXENV_UNDI_FORCE_INTERRUPT {
+ PXENV_STATUS_t Status; /**< PXE status code */
+} PACKED;
+
+typedef struct s_PXENV_UNDI_FORCE_INTERRUPT PXENV_UNDI_FORCE_INTERRUPT_t;
+
+extern PXENV_EXIT_t pxenv_undi_force_interrupt (
+ struct s_PXENV_UNDI_FORCE_INTERRUPT *undi_force_interrupt );
+
+/** @} */ /* pxenv_undi_force_interrupt */
+
+/** @defgroup pxenv_undi_get_mcast_address PXENV_UNDI_GET_MCAST_ADDRESS
+ *
+ * UNDI GET MULTICAST ADDRESS
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_get_mcast_address() */
+#define PXENV_UNDI_GET_MCAST_ADDRESS 0x0011
+
+/** Parameter block for pxenv_undi_get_mcast_address() */
+struct s_PXENV_UNDI_GET_MCAST_ADDRESS {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ IP4_t InetAddr; /**< Multicast IP address */
+ MAC_ADDR_t MediaAddr; /**< Multicast MAC address */
+} PACKED;
+
+typedef struct s_PXENV_UNDI_GET_MCAST_ADDRESS PXENV_UNDI_GET_MCAST_ADDRESS_t;
+
+extern PXENV_EXIT_t pxenv_undi_get_mcast_address (
+ struct s_PXENV_UNDI_GET_MCAST_ADDRESS *undi_get_mcast_address );
+
+/** @} */ /* pxenv_undi_get_mcast_address */
+
+/** @defgroup pxenv_undi_get_nic_type PXENV_UNDI_GET_NIC_TYPE
+ *
+ * UNDI GET NIC TYPE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_get_nic_type() */
+#define PXENV_UNDI_GET_NIC_TYPE 0x0012
+
+#define PCI_NIC 2 /**< PCI network card */
+#define PnP_NIC 3 /**< ISAPnP network card */
+#define CardBus_NIC 4 /**< CardBus network card */
+
+/** Information for a PCI or equivalent NIC */
+struct pci_nic_info {
+ UINT16_t Vendor_ID; /**< PCI vendor ID */
+ UINT16_t Dev_ID; /**< PCI device ID */
+ UINT8_t Base_Class; /**< PCI base class */
+ UINT8_t Sub_Class; /**< PCI sub class */
+ UINT8_t Prog_Intf; /**< PCI programming interface */
+ UINT8_t Rev; /**< PCI revision */
+ UINT16_t BusDevFunc; /**< PCI bus:dev:fn address */
+ UINT16_t SubVendor_ID; /**< PCI subvendor ID */
+ UINT16_t SubDevice_ID; /**< PCI subdevice ID */
+} PACKED;
+
+/** Information for an ISAPnP or equivalent NIC */
+struct pnp_nic_info {
+ UINT32_t EISA_Dev_ID; /**< EISA device ID */
+ UINT8_t Base_Class; /**< Base class */
+ UINT8_t Sub_Class; /**< Sub class */
+ UINT8_t Prog_Intf; /**< Programming interface */
+ /** Card Select Number assigned to card */
+ UINT16_t CardSelNum;
+} PACKED;
+
+/** Parameter block for pxenv_undi_get_nic_type() */
+struct s_PXENV_UNDI_GET_NIC_TYPE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** NIC type
+ *
+ * Valid values are #PCI_NIC, #PnP_NIC or #CardBus_NIC.
+ */
+ UINT8_t NicType;
+ /** NIC information */
+ union nic_type_info {
+ /** NIC information (if #NicType==#PCI_NIC) */
+ struct pci_nic_info pci;
+ /** NIC information (if #NicType==#CardBus_NIC) */
+ struct pci_nic_info cardbus;
+ /** NIC information (if #NicType==#PnP_NIC) */
+ struct pnp_nic_info pnp;
+ } info;
+} PACKED;
+
+typedef struct s_PXENV_UNDI_GET_NIC_TYPE PXENV_UNDI_GET_NIC_TYPE_t;
+
+extern PXENV_EXIT_t pxenv_undi_get_nic_type (
+ struct s_PXENV_UNDI_GET_NIC_TYPE *undi_get_nic_type );
+
+/** @} */ /* pxenv_undi_get_nic_type */
+
+/** @defgroup pxenv_undi_get_iface_info PXENV_UNDI_GET_IFACE_INFO
+ *
+ * UNDI GET IFACE INFO
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_get_iface_info() */
+#define PXENV_UNDI_GET_IFACE_INFO 0x0013
+
+/** Parameter block for pxenv_undi_get_iface_info() */
+struct s_PXENV_UNDI_GET_IFACE_INFO {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** Interface type
+ *
+ * This is defined in the NDIS 2.0 specification to be one of
+ * the strings "802.3", "802.4", "802.5", "802.6", "DIX",
+ * "DIX+802.3", "APPLETALK", "ARCNET", "FDDI", "SDLC", "BSC",
+ * "HDLC", or "ISDN".
+ *
+ * "Normal" Ethernet, for various historical reasons, is
+ * "DIX+802.3".
+ */
+ UINT8_t IfaceType[16];
+ UINT32_t LinkSpeed; /**< Link speed, in bits per second */
+ /** Service flags
+ *
+ * These are the "service flags" defined in the "MAC
+ * Service-Specific Characteristics" table in the NDIS 2.0
+ * specification. Almost all of them are irrelevant to PXE.
+ */
+ UINT32_t ServiceFlags;
+ UINT32_t Reserved[4]; /**< Must be zero */
+} PACKED;
+
+typedef struct s_PXENV_UNDI_GET_IFACE_INFO PXENV_UNDI_GET_IFACE_INFO_t;
+
+extern PXENV_EXIT_t pxenv_undi_get_iface_info (
+ struct s_PXENV_UNDI_GET_IFACE_INFO *undi_get_iface_info );
+
+/** @} */ /* pxenv_undi_get_iface_info */
+
+/** @defgroup pxenv_undi_get_state PXENV_UNDI_GET_STATE
+ *
+ * UNDI GET STATE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_get_state() */
+#define PXENV_UNDI_GET_STATE 0x0015
+
+/** pxenv_start_undi() has been called */
+#define PXE_UNDI_GET_STATE_STARTED 1
+/** pxenv_undi_initialize() has been called */
+#define PXE_UNDI_GET_STATE_INITIALIZED 2
+/** pxenv_undi_open() has been called */
+#define PXE_UNDI_GET_STATE_OPENED 3
+
+/** Parameter block for pxenv_undi_get_state() */
+struct s_PXENV_UNDI_GET_STATE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** Current state of the UNDI driver
+ *
+ * Valid values are #PXE_UNDI_GET_STATE_STARTED,
+ * #PXE_UNDI_GET_STATE_INITIALIZED or
+ * #PXE_UNDI_GET_STATE_OPENED.
+ */
+ UINT8_t UNDIstate;
+} PACKED;
+
+typedef struct s_PXENV_UNDI_GET_STATE PXENV_UNDI_GET_STATE_t;
+
+extern PXENV_EXIT_t pxenv_undi_get_state ( struct s_PXENV_UNDI_GET_STATE
+ *undi_get_state );
+
+/** @} */ /* pxenv_undi_get_state */
+
+/** @defgroup pxenv_undi_isr PXENV_UNDI_ISR
+ *
+ * UNDI ISR
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_undi_isr() */
+#define PXENV_UNDI_ISR 0x0014
+
+/** Determine whether or not this is our interrupt */
+#define PXENV_UNDI_ISR_IN_START 1
+/** Start processing interrupt */
+#define PXENV_UNDI_ISR_IN_PROCESS 2
+/** Continue processing interrupt */
+#define PXENV_UNDI_ISR_IN_GET_NEXT 3
+/** This interrupt was ours */
+#define PXENV_UNDI_ISR_OUT_OURS 0
+/** This interrupt was not ours */
+#define PXENV_UNDI_ISR_OUT_NOT_OURS 1
+/** Finished processing interrupt */
+#define PXENV_UNDI_ISR_OUT_DONE 0
+/** A packet transmission has completed */
+#define PXENV_UNDI_ISR_OUT_TRANSMIT 2
+/** A packet has been received */
+#define PXENV_UNDI_ISR_OUT_RECEIVE 3
+/** We are already in the middle of processing an interrupt */
+#define PXENV_UNDI_ISR_OUT_BUSY 4
+
+/** Unicast packet (or packet captured in promiscuous mode) */
+#define P_DIRECTED 0
+/** Broadcast packet */
+#define P_BROADCAST 1
+/** Multicast packet */
+#define P_MULTICAST 2
+
+/** Parameter block for pxenv_undi_isr() */
+struct s_PXENV_UNDI_ISR {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ /** Function flag
+ *
+ * Valid values are #PXENV_UNDI_ISR_IN_START,
+ * #PXENV_UNDI_ISR_IN_PROCESS, #PXENV_UNDI_ISR_IN_GET_NEXT,
+ * #PXENV_UNDI_ISR_OUT_OURS, #PXENV_UNDI_ISR_OUT_NOT_OURS,
+ * #PXENV_UNDI_ISR_OUT_DONE, #PXENV_UNDI_ISR_OUT_TRANSMIT,
+ * #PXENV_UNDI_ISR_OUT_RECEIVE or #PXENV_UNDI_ISR_OUT_BUSY.
+ */
+ UINT16_t FuncFlag;
+ UINT16_t BufferLength; /**< Data buffer length */
+ UINT16_t FrameLength; /**< Total frame length */
+ UINT16_t FrameHeaderLength; /**< Frame header length */
+ SEGOFF16_t Frame; /**< Data buffer address */
+ /** Protocol type
+ *
+ * Valid values are #P_IP, #P_ARP, #P_RARP or #P_OTHER.
+ */
+ UINT8_t ProtType;
+ /** Packet type
+ *
+ * Valid values are #P_DIRECTED, #P_BROADCAST or #P_MULTICAST.
+ */
+ UINT8_t PktType;
+} PACKED;
+
+typedef struct s_PXENV_UNDI_ISR PXENV_UNDI_ISR_t;
+
+extern PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr );
+
+/** @} */ /* pxenv_undi_isr */
+
+/** @} */ /* pxe_undi_api */
+
+/** @defgroup pxe_file_api PXE FILE API
+ *
+ * POSIX-like file operations
+ *
+ * @{
+ */
+
+/** @defgroup pxenv_file_open PXENV_FILE_OPEN
+ *
+ * FILE OPEN
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_open() */
+#define PXENV_FILE_OPEN 0x00e0
+
+/** Parameter block for pxenv_file_open() */
+struct s_PXENV_FILE_OPEN {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT16_t FileHandle; /**< File handle */
+ SEGOFF16_t FileName; /**< File URL */
+ UINT32_t Reserved; /**< Reserved */
+} PACKED;
+
+typedef struct s_PXENV_FILE_OPEN PXENV_FILE_OPEN_t;
+
+extern PXENV_EXIT_t pxenv_file_open ( struct s_PXENV_FILE_OPEN *file_open );
+
+/** @} */ /* pxenv_file_open */
+
+/** @defgroup pxenv_file_close PXENV_FILE_CLOSE
+ *
+ * FILE CLOSE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_close() */
+#define PXENV_FILE_CLOSE 0x00e1
+
+/** Parameter block for pxenv_file_close() */
+struct s_PXENV_FILE_CLOSE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT16_t FileHandle; /**< File handle */
+} PACKED;
+
+typedef struct s_PXENV_FILE_CLOSE PXENV_FILE_CLOSE_t;
+
+extern PXENV_EXIT_t pxenv_file_close ( struct s_PXENV_FILE_CLOSE
+ *file_close );
+
+/** @} */ /* pxenv_file_close */
+
+/** @defgroup pxenv_file_select PXENV_FILE_SELECT
+ *
+ * FILE SELECT
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_select() */
+#define PXENV_FILE_SELECT 0x00e2
+
+/** File is ready for reading */
+#define RDY_READ 0x0001
+
+/** Parameter block for pxenv_file_select() */
+struct s_PXENV_FILE_SELECT {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT16_t FileHandle; /**< File handle */
+ UINT16_t Ready; /**< Indication of readiness */
+} PACKED;
+
+typedef struct s_PXENV_FILE_SELECT PXENV_FILE_SELECT_t;
+
+extern PXENV_EXIT_t pxenv_file_select ( struct s_PXENV_FILE_SELECT
+ *file_select );
+
+/** @} */ /* pxenv_file_select */
+
+/** @defgroup pxenv_file_read PXENV_FILE_READ
+ *
+ * FILE READ
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_read() */
+#define PXENV_FILE_READ 0x00e3
+
+/** Parameter block for pxenv_file_read() */
+struct s_PXENV_FILE_READ {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT16_t FileHandle; /**< File handle */
+ UINT16_t BufferSize; /**< Data buffer size */
+ SEGOFF16_t Buffer; /**< Data buffer */
+} PACKED;
+
+typedef struct s_PXENV_FILE_READ PXENV_FILE_READ_t;
+
+extern PXENV_EXIT_t pxenv_file_read ( struct s_PXENV_FILE_READ *file_read );
+
+/** @} */ /* pxenv_file_read */
+
+/** @defgroup pxenv_get_file_size PXENV_GET_FILE_SIZE
+ *
+ * GET FILE SIZE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_get_file_size() */
+#define PXENV_GET_FILE_SIZE 0x00e4
+
+/** Parameter block for pxenv_get_file_size() */
+struct s_PXENV_GET_FILE_SIZE {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT16_t FileHandle; /**< File handle */
+ UINT32_t FileSize; /**< File size */
+} PACKED;
+
+typedef struct s_PXENV_GET_FILE_SIZE PXENV_GET_FILE_SIZE_t;
+
+extern PXENV_EXIT_t pxenv_get_file_size ( struct s_PXENV_GET_FILE_SIZE
+ *get_file_size );
+
+/** @} */ /* pxenv_get_file_size */
+
+/** @defgroup pxenv_file_exec PXENV_FILE_EXEC
+ *
+ * FILE EXEC
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_exec() */
+#define PXENV_FILE_EXEC 0x00e5
+
+/** Parameter block for pxenv_file_exec() */
+struct s_PXENV_FILE_EXEC {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ SEGOFF16_t Command; /**< Command to execute */
+} PACKED;
+
+typedef struct s_PXENV_FILE_EXEC PXENV_FILE_EXEC_t;
+
+extern PXENV_EXIT_t pxenv_file_exec ( struct s_PXENV_FILE_EXEC *file_exec );
+
+/** @} */ /* pxenv_file_exec */
+
+/** @defgroup pxenv_file_api_check PXENV_FILE_API_CHECK
+ *
+ * FILE API CHECK
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_api_check() */
+#define PXENV_FILE_API_CHECK 0x00e6
+
+/** Parameter block for pxenv_file_api_check() */
+struct s_PXENV_FILE_API_CHECK {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ UINT16_t Size; /**< Size of structure */
+ UINT32_t Magic; /**< Magic number */
+ UINT32_t Provider; /**< Implementation identifier */
+ UINT32_t APIMask; /**< Supported API functions */
+ UINT32_t Flags; /**< Reserved for the future */
+} PACKED;
+
+typedef struct s_PXENV_FILE_API_CHECK PXENV_FILE_API_CHECK_t;
+
+extern PXENV_EXIT_t pxenv_file_api_check ( struct s_PXENV_FILE_API_CHECK *file_api_check );
+
+/** @} */ /* pxenv_file_api_check */
+
+/** @} */ /* pxe_file_api */
+
+/** @defgroup pxe_loader_api PXE Loader API
+ *
+ * The UNDI ROM loader API
+ *
+ * @{
+ */
+
+/** Parameter block for undi_loader() */
+struct s_UNDI_LOADER {
+ /** PXE status code */
+ PXENV_STATUS_t Status;
+ /** %ax register as for PXENV_START_UNDI */
+ UINT16_t AX;
+ /** %bx register as for PXENV_START_UNDI */
+ UINT16_t BX;
+ /** %dx register as for PXENV_START_UNDI */
+ UINT16_t DX;
+ /** %di register as for PXENV_START_UNDI */
+ OFF16_t DI;
+ /** %es register as for PXENV_START_UNDI */
+ SEGSEL_t ES;
+ /** UNDI data segment
+ *
+ * @note The PXE specification defines the type of this field
+ * as #UINT16_t. For x86, #SEGSEL_t and #UINT16_t are
+ * equivalent anyway; for other architectures #SEGSEL_t makes
+ * more sense.
+ */
+ SEGSEL_t UNDI_DS;
+ /** UNDI code segment
+ *
+ * @note The PXE specification defines the type of this field
+ * as #UINT16_t. For x86, #SEGSEL_t and #UINT16_t are
+ * equivalent anyway; for other architectures #SEGSEL_t makes
+ * more sense.
+ */
+ SEGSEL_t UNDI_CS;
+ /** Address of the !PXE structure (a struct s_PXE) */
+ SEGOFF16_t PXEptr;
+ /** Address of the PXENV+ structure (a struct s_PXENV) */
+ SEGOFF16_t PXENVptr;
+} PACKED;
+
+typedef struct s_UNDI_LOADER UNDI_LOADER_t;
+
+extern PXENV_EXIT_t undi_loader ( struct s_UNDI_LOADER *undi_loader );
+
+/** @} */ /* pxe_loader_api */
+
+/** @} */ /* pxe */
+
+/** @page pxe_notes Etherboot PXE implementation notes
+
+@section pxe_routing IP routing
+
+Several PXE API calls (e.g. pxenv_tftp_open() and pxenv_udp_write())
+allow for the caller to specify a "relay agent IP address", often in a
+field called "gateway" or similar. The PXE specification states that
+"The IP layer should provide space for a minimum of four routing
+entries obtained from the default router and static route DHCP option
+tags in the DHCPACK message, plus any non-zero giaddr field from the
+DHCPOFFER message(s) accepted by the client".
+
+The DHCP static route option ("option static-routes" in dhcpd.conf)
+works only for classed IP routing (i.e. it provides no way to specify
+a subnet mask). Since virtually everything now uses classless IP
+routing, the DHCP static route option is almost totally useless, and
+is (according to the dhcp-options man page) not implemented by any of
+the popular DHCP clients.
+
+This leaves the caller-specified "relay agent IP address", the giaddr
+field from the DHCPOFFER message(s) and the default gateway(s)
+provided via the routers option ("option routers" in dhcpd.conf) in
+the DHCPACK message. Each of these is a default gateway address.
+It's a fair bet that the routers option should take priority over the
+giaddr field, since the routers option has to be explicitly specified
+by the DHCP server operator. Similarly, it's fair to assume that the
+caller-specified "relay agent IP address", if present, should take
+priority over any other routing table entries.
+
+@bug Etherboot currently ignores all potential sources of routing
+information other than the first router provided to it by a DHCP
+routers option.
+
+@section pxe_x86_modes x86 processor mode restrictions
+
+On the x86 platform, different PXE API calls have different
+restrictions on the processor modes (real or protected) that can be
+used. See the individual API call descriptions for the restrictions
+that apply to any particular call.
+
+@subsection pxe_x86_pmode16 Real mode, or protected-mode with 16-bit stack
+
+The PXE specification states that the API function can be called in
+protected mode only if the s_PXE::StatusCallout field is set to a
+non-zero value, and that the API function cannot be called with a
+32-bit stack segment.
+
+Etherboot does not enforce either of these restrictions; they seem (as
+with so much of the PXE specification) to be artifacts of the Intel
+implementation.
+
+*/
+
+#endif /* PXE_API_H */
diff --git a/gpxe/src/include/pxe_types.h b/gpxe/src/include/pxe_types.h
new file mode 100644
index 00000000..e31af062
--- /dev/null
+++ b/gpxe/src/include/pxe_types.h
@@ -0,0 +1,126 @@
+#ifndef PXE_TYPES_H
+#define PXE_TYPES_H
+
+/** @file
+ *
+ * PXE data types
+ *
+ */
+
+#include "stdint.h"
+#include "pxe_addr.h" /* Architecture-specific PXE definitions */
+#include "errno.h" /* PXE status codes */
+
+/** @addtogroup pxe Preboot eXecution Environment (PXE) API
+ * @{
+ */
+
+/** @defgroup pxe_types PXE data types
+ *
+ * Basic PXE data types such as #UINT16_t, #ADDR32_t, #SEGSEL_t etc.
+ *
+ * These definitions are based on Table 1-1 ("Data Type Definitions")
+ * in the Intel PXE specification version 2.1. They have been
+ * generalised to non-x86 architectures where possible.
+ *
+ * @{
+ */
+
+/** An 8-bit unsigned integer */
+typedef uint8_t UINT8_t;
+
+/** A 16-bit unsigned integer */
+typedef uint16_t UINT16_t;
+
+/** A 32-bit unsigned integer */
+typedef uint32_t UINT32_t;
+
+/** A PXE exit code.
+ *
+ * Permitted values are #PXENV_EXIT_SUCCESS and #PXENV_EXIT_FAILURE.
+ *
+ */
+typedef UINT16_t PXENV_EXIT_t;
+#define PXENV_EXIT_SUCCESS 0x0000 /**< No error occurred */
+#define PXENV_EXIT_FAILURE 0x0001 /**< An error occurred */
+
+/** A PXE status code.
+ *
+ * Status codes are defined in errno.h.
+ *
+ */
+typedef UINT16_t PXENV_STATUS_t;
+
+/** An IPv4 address.
+ *
+ * @note This data type is in network (big-endian) byte order.
+ *
+ */
+typedef UINT32_t IP4_t;
+
+/** A UDP port.
+ *
+ * @note This data type is in network (big-endian) byte order.
+ *
+ */
+typedef UINT16_t UDP_PORT_t;
+
+/** Maximum length of a MAC address */
+#define MAC_ADDR_LEN 16
+
+/** A MAC address */
+typedef UINT8_t MAC_ADDR_t[MAC_ADDR_LEN];
+
+#ifndef HAVE_ARCH_ADDR32
+/** A physical address.
+ *
+ * For x86, this is a 32-bit physical address, and is therefore
+ * limited to the low 4GB.
+ *
+ */
+typedef UINT32_t ADDR32_t;
+#endif
+
+#ifndef HAVE_ARCH_SEGSEL
+/** A segment selector.
+ *
+ * For x86, this is a real mode segment (0x0000-0xffff), or a
+ * protected-mode segment selector, such as could be loaded into a
+ * segment register.
+ *
+ */
+typedef UINT16_t SEGSEL_t;
+#endif
+
+#ifndef HAVE_ARCH_OFF16
+/** An offset within a segment identified by #SEGSEL
+ *
+ * For x86, this is a 16-bit offset.
+ *
+ */
+typedef UINT16_t OFF16_t;
+#endif
+
+/** A segment:offset address
+ *
+ * For x86, this is a 16-bit real-mode or protected-mode
+ * segment:offset address.
+ *
+ */
+typedef struct s_SEGOFF16 {
+ OFF16_t offset; /**< Offset within the segment */
+ SEGSEL_t segment; /**< Segment selector */
+} PACKED SEGOFF16_t;
+
+/** A segment descriptor */
+typedef struct s_SEGDESC {
+ SEGSEL_t segment_address; /**< Segment selector */
+ ADDR32_t Physical_address; /**< Segment base address */
+ OFF16_t Seg_size; /**< Size of the segment */
+} PACKED SEGDESC_t;
+
+/** @} */ /* pxe_types */
+
+/** @} */ /* pxe */
+
+#endif /* PXE_TYPES_H */
diff --git a/gpxe/src/include/readline/readline.h b/gpxe/src/include/readline/readline.h
new file mode 100644
index 00000000..1a03b483
--- /dev/null
+++ b/gpxe/src/include/readline/readline.h
@@ -0,0 +1,12 @@
+#ifndef _READLINE_H
+#define _READLINE_H
+
+/** @file
+ *
+ * Minmal readline
+ *
+ */
+
+extern char * __malloc readline ( const char *prompt );
+
+#endif /* _READLINE_H */
diff --git a/gpxe/src/include/stdarg.h b/gpxe/src/include/stdarg.h
new file mode 100644
index 00000000..a4eb711d
--- /dev/null
+++ b/gpxe/src/include/stdarg.h
@@ -0,0 +1,10 @@
+#ifndef _STDARG_H
+#define _STDARG_H
+
+typedef __builtin_va_list va_list;
+#define va_start( ap, last ) __builtin_va_start ( ap, last )
+#define va_arg( ap, type ) __builtin_va_arg ( ap, type )
+#define va_end( ap ) __builtin_va_end ( ap )
+#define va_copy( dest, src ) __builtin_va_copy ( dest, src )
+
+#endif /* _STDARG_H */
diff --git a/gpxe/src/include/stddef.h b/gpxe/src/include/stddef.h
new file mode 100644
index 00000000..6f91d219
--- /dev/null
+++ b/gpxe/src/include/stddef.h
@@ -0,0 +1,18 @@
+#ifndef STDDEF_H
+#define STDDEF_H
+
+/* for size_t */
+#include <stdint.h>
+
+#undef NULL
+#define NULL ((void *)0)
+
+#undef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+#undef container_of
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
+#endif /* STDDEF_H */
diff --git a/gpxe/src/include/stdint.h b/gpxe/src/include/stdint.h
new file mode 100644
index 00000000..4b0e44f2
--- /dev/null
+++ b/gpxe/src/include/stdint.h
@@ -0,0 +1,24 @@
+#ifndef _STDINT_H
+#define _STDINT_H
+
+#include <bits/stdint.h>
+
+typedef int8_t s8;
+typedef uint8_t u8;
+typedef int16_t s16;
+typedef uint16_t u16;
+typedef int32_t s32;
+typedef uint32_t u32;
+typedef int64_t s64;
+typedef uint64_t u64;
+
+typedef int8_t int8;
+typedef uint8_t uint8;
+typedef int16_t int16;
+typedef uint16_t uint16;
+typedef int32_t int32;
+typedef uint32_t uint32;
+typedef int64_t int64;
+typedef uint64_t uint64;
+
+#endif /* _STDINT_H */
diff --git a/gpxe/src/include/stdio.h b/gpxe/src/include/stdio.h
new file mode 100644
index 00000000..82077e20
--- /dev/null
+++ b/gpxe/src/include/stdio.h
@@ -0,0 +1,45 @@
+#ifndef _STDIO_H
+#define _STDIO_H
+
+#include <stdint.h>
+#include <stdarg.h>
+
+extern int __attribute__ (( format ( printf, 1, 2 ) ))
+printf ( const char *fmt, ... );
+
+extern int __attribute__ (( format ( printf, 3, 4 ) ))
+snprintf ( char *buf, size_t size, const char *fmt, ... );
+
+extern int __attribute__ (( format ( printf, 2, 3 ) ))
+asprintf ( char **strp, const char *fmt, ... );
+
+extern int vprintf ( const char *fmt, va_list args );
+
+extern int vsnprintf ( char *buf, size_t size, const char *fmt, va_list args );
+
+extern int vasprintf ( char **strp, const char *fmt, va_list args );
+
+/**
+ * Write a formatted string to a buffer
+ *
+ * @v buf Buffer into which to write the string
+ * @v fmt Format string
+ * @v ... Arguments corresponding to the format string
+ * @ret len Length of formatted string
+ */
+#define sprintf( buf, fmt, ... ) \
+ snprintf ( (buf), ~( ( size_t ) 0 ), (fmt), ## __VA_ARGS__ )
+
+/**
+ * Write a formatted string to a buffer
+ *
+ * @v buf Buffer into which to write the string
+ * @v fmt Format string
+ * @v args Arguments corresponding to the format string
+ * @ret len Length of formatted string
+ */
+static inline int vsprintf ( char *buf, const char *fmt, va_list args ) {
+ return vsnprintf ( buf, ~( ( size_t ) 0 ), fmt, args );
+}
+
+#endif /* _STDIO_H */
diff --git a/gpxe/src/include/stdlib.h b/gpxe/src/include/stdlib.h
new file mode 100644
index 00000000..ae996962
--- /dev/null
+++ b/gpxe/src/include/stdlib.h
@@ -0,0 +1,72 @@
+#ifndef STDLIB_H
+#define STDLIB_H
+
+#include <stdint.h>
+#include <assert.h>
+
+/*****************************************************************************
+ *
+ * Numeric parsing
+ *
+ ****************************************************************************
+ */
+
+extern unsigned long strtoul ( const char *p, char **endp, int base );
+
+/*****************************************************************************
+ *
+ * Memory allocation
+ *
+ ****************************************************************************
+ */
+
+extern void * __malloc malloc ( size_t size );
+extern void * realloc ( void *old_ptr, size_t new_size );
+extern void free ( void *ptr );
+extern void * __malloc zalloc ( size_t len );
+
+/**
+ * Allocate cleared memory
+ *
+ * @v nmemb Number of members
+ * @v size Size of each member
+ * @ret ptr Allocated memory
+ *
+ * Allocate memory as per malloc(), and zero it.
+ *
+ * This is implemented as a static inline, with the body of the
+ * function in zalloc(), since in most cases @c nmemb will be 1 and
+ * doing the multiply is just wasteful.
+ */
+static inline void * __malloc calloc ( size_t nmemb, size_t size ) {
+ return zalloc ( nmemb * size );
+}
+
+/*****************************************************************************
+ *
+ * Random number generation
+ *
+ ****************************************************************************
+ */
+
+extern long int random ( void );
+extern void srandom ( unsigned int seed );
+
+static inline int rand ( void ) {
+ return random();
+}
+
+static inline void srand ( unsigned int seed ) {
+ srandom ( seed );
+}
+
+/*****************************************************************************
+ *
+ * Miscellaneous
+ *
+ ****************************************************************************
+ */
+
+extern int system ( const char *command );
+
+#endif /* STDLIB_H */
diff --git a/gpxe/src/include/string.h b/gpxe/src/include/string.h
new file mode 100644
index 00000000..a2894a3a
--- /dev/null
+++ b/gpxe/src/include/string.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 2004 Tobias Lorenz
+ *
+ * string handling functions
+ * based on linux/include/linux/ctype.h
+ * and linux/include/linux/string.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef ETHERBOOT_STRING_H
+#define ETHERBOOT_STRING_H
+
+#include <stddef.h>
+#include <bits/string.h>
+
+int __pure strnicmp(const char *s1, const char *s2, size_t len) __nonnull;
+char * strcpy(char * dest,const char *src) __nonnull;
+char * strncpy(char * dest,const char *src,size_t count) __nonnull;
+char * strcat(char * dest, const char * src) __nonnull;
+char * strncat(char *dest, const char *src, size_t count) __nonnull;
+int __pure strcmp(const char * cs,const char * ct) __nonnull;
+int __pure strncmp(const char * cs,const char * ct,
+ size_t count) __nonnull;
+char * __pure strchr(const char * s, int c) __nonnull;
+char * __pure strrchr(const char * s, int c) __nonnull;
+size_t __pure strlen(const char * s) __nonnull;
+size_t __pure strnlen(const char * s, size_t count) __nonnull;
+size_t __pure strspn(const char *s, const char *accept) __nonnull;
+size_t __pure strcspn(const char *s, const char *reject) __nonnull;
+char * __pure strpbrk(const char * cs,const char * ct) __nonnull;
+char * strtok(char * s,const char * ct) __nonnull;
+char * strsep(char **s, const char *ct) __nonnull;
+void * memset(void * s,int c,size_t count) __nonnull;
+void * memmove(void * dest,const void *src,size_t count) __nonnull;
+int __pure memcmp(const void * cs,const void * ct,
+ size_t count) __nonnull;
+void * __pure memscan(const void * addr, int c, size_t size) __nonnull;
+char * __pure strstr(const char * s1,const char * s2) __nonnull;
+void * __pure memchr(const void *s, int c, size_t n) __nonnull;
+char * __malloc strdup(const char *s) __nonnull;
+char * __malloc strndup(const char *s, size_t n) __nonnull;
+
+extern const char * __pure strerror ( int errno );
+
+#endif /* ETHERBOOT_STRING */
diff --git a/gpxe/src/include/strings.h b/gpxe/src/include/strings.h
new file mode 100644
index 00000000..968a7c11
--- /dev/null
+++ b/gpxe/src/include/strings.h
@@ -0,0 +1,63 @@
+#ifndef _STRINGS_H
+#define _STRINGS_H
+
+#include <limits.h>
+#include <string.h>
+
+static inline __attribute__ (( always_inline )) int
+__constant_flsl ( unsigned long x ) {
+ int r = 0;
+
+#if ULONG_MAX > 0xffffffff
+ if ( x & 0xffffffff00000000UL ) {
+ x >>= 32;
+ r += 32;
+ }
+#endif
+ if ( x & 0xffff0000UL ) {
+ x >>= 16;
+ r += 16;
+ }
+ if ( x & 0xff00 ) {
+ x >>= 8;
+ r += 8;
+ }
+ if ( x & 0xf0 ) {
+ x >>= 4;
+ r += 4;
+ }
+ if ( x & 0xc ) {
+ x >>= 2;
+ r += 2;
+ }
+ if ( x & 0x2 ) {
+ x >>= 1;
+ r += 1;
+ }
+ if ( x & 0x1 ) {
+ r += 1;
+ }
+ return r;
+}
+
+/* We don't actually have these functions yet */
+extern int __flsl ( long x );
+
+#define flsl( x ) \
+ ( __builtin_constant_p ( x ) ? __constant_flsl ( x ) : __flsl ( x ) )
+
+#define fls( x ) flsl ( x )
+
+extern int strcasecmp ( const char *s1, const char *s2 );
+
+static inline __attribute__ (( always_inline )) void
+bcopy ( const void *src, void *dest, size_t n ) {
+ memmove ( dest, src, n );
+}
+
+static inline __attribute__ (( always_inline )) void
+bzero ( void *s, size_t n ) {
+ memset ( s, 0, n );
+}
+
+#endif /* _STRINGS_H */
diff --git a/gpxe/src/include/sys/time.h b/gpxe/src/include/sys/time.h
new file mode 100644
index 00000000..21fb7e99
--- /dev/null
+++ b/gpxe/src/include/sys/time.h
@@ -0,0 +1,20 @@
+#ifndef _SYS_TIME_H
+#define _SYS_TIME_H
+
+#include <time.h>
+
+typedef unsigned long suseconds_t;
+
+struct timeval {
+ time_t tv_sec; /* seconds */
+ suseconds_t tv_usec; /* microseconds */
+};
+
+struct timezone {
+ int tz_minuteswest; /* minutes W of Greenwich */
+ int tz_dsttime; /* type of dst correction */
+};
+
+extern int gettimeofday ( struct timeval *tv, struct timezone *tz );
+
+#endif /* _SYS_TIME_H */
diff --git a/gpxe/src/include/sys_info.h b/gpxe/src/include/sys_info.h
new file mode 100644
index 00000000..7127c643
--- /dev/null
+++ b/gpxe/src/include/sys_info.h
@@ -0,0 +1,33 @@
+#ifndef SYS_INFO_H
+#define SYS_INFO_H
+
+/* Information collected from firmware/bootloader */
+
+struct sys_info {
+ /* Values passed by bootloader */
+ unsigned long boot_type;
+ unsigned long boot_data;
+ unsigned long boot_arg;
+
+ char *firmware; /* "PCBIOS", "LinuxBIOS", etc. */
+ char *command_line; /* command line given to us */
+#if 0
+//By LYH
+//Will use meminfo in Etherboot
+ /* memory map */
+ int n_memranges;
+ struct memrange {
+ unsigned long long base;
+ unsigned long long size;
+ } *memrange;
+#endif
+};
+
+void collect_sys_info(struct sys_info *info);
+void collect_elfboot_info(struct sys_info *info);
+void collect_linuxbios_info(struct sys_info *info);
+
+/* Our name and version. I want to see single instance of these in the image */
+extern const char *program_name, *program_version;
+
+#endif /* SYS_INFO_H */
diff --git a/gpxe/src/include/time.h b/gpxe/src/include/time.h
new file mode 100644
index 00000000..6ea927c3
--- /dev/null
+++ b/gpxe/src/include/time.h
@@ -0,0 +1,22 @@
+#ifndef _TIME_H
+#define _TIME_H
+
+typedef unsigned long time_t;
+
+struct tm {
+ int tm_sec; /* seconds */
+ int tm_min; /* minutes */
+ int tm_hour; /* hours */
+ int tm_mday; /* day of the month */
+ int tm_mon; /* month */
+ int tm_year; /* year */
+ int tm_wday; /* day of the week */
+ int tm_yday; /* day in the year */
+ int tm_isdst; /* daylight saving time */
+};
+
+extern time_t time ( time_t *t );
+
+extern time_t mktime ( struct tm *tm );
+
+#endif /* _TIME_H */
diff --git a/gpxe/src/include/unistd.h b/gpxe/src/include/unistd.h
new file mode 100644
index 00000000..7c44a0ce
--- /dev/null
+++ b/gpxe/src/include/unistd.h
@@ -0,0 +1,31 @@
+#ifndef _UNISTD_H
+#define _UNISTD_H
+
+#include <stddef.h>
+#include <stdarg.h>
+
+unsigned int sleep ( unsigned int seconds );
+extern int execv ( const char *command, char * const argv[] );
+
+/**
+ * Execute command
+ *
+ * @v command Command name
+ * @v arg ... Argument list (starting with argv[0])
+ * @ret rc Command exit status
+ *
+ * This is a front end to execv().
+ */
+#define execl( command, arg, ... ) ( { \
+ char * const argv[] = { (arg), ## __VA_ARGS__ }; \
+ int rc = execv ( (command), argv ); \
+ rc; \
+ } )
+
+void udelay(unsigned int usecs);
+void mdelay(unsigned int msecs);
+
+#define usleep(x) udelay(x)
+
+
+#endif /* _UNISTD_H */
diff --git a/gpxe/src/include/usr/aoeboot.h b/gpxe/src/include/usr/aoeboot.h
new file mode 100644
index 00000000..0421ebcc
--- /dev/null
+++ b/gpxe/src/include/usr/aoeboot.h
@@ -0,0 +1,6 @@
+#ifndef _USR_AOEBOOT_H
+#define _USR_AOEBOOT_H
+
+extern int aoeboot ( const char *root_path );
+
+#endif /* _USR_AOEBOOT_H */
diff --git a/gpxe/src/include/usr/autoboot.h b/gpxe/src/include/usr/autoboot.h
new file mode 100644
index 00000000..b451a8c1
--- /dev/null
+++ b/gpxe/src/include/usr/autoboot.h
@@ -0,0 +1,13 @@
+#ifndef _USR_AUTOBOOT_H
+#define _USR_AUTOBOOT_H
+
+/** @file
+ *
+ * Automatic booting
+ *
+ */
+
+extern void autoboot ( void );
+extern int boot_root_path ( const char *root_path );
+
+#endif /* _USR_AUTOBOOT_H */
diff --git a/gpxe/src/include/usr/dhcpmgmt.h b/gpxe/src/include/usr/dhcpmgmt.h
new file mode 100644
index 00000000..2757a1c1
--- /dev/null
+++ b/gpxe/src/include/usr/dhcpmgmt.h
@@ -0,0 +1,14 @@
+#ifndef _USR_DHCPMGMT_H
+#define _USR_DHCPMGMT_H
+
+/** @file
+ *
+ * DHCP management
+ *
+ */
+
+struct net_device;
+
+int dhcp ( struct net_device *netdev );
+
+#endif /* _USR_DHCPMGMT_H */
diff --git a/gpxe/src/include/usr/ifmgmt.h b/gpxe/src/include/usr/ifmgmt.h
new file mode 100644
index 00000000..c7d35da8
--- /dev/null
+++ b/gpxe/src/include/usr/ifmgmt.h
@@ -0,0 +1,16 @@
+#ifndef _USR_IFMGMT_H
+#define _USR_IFMGMT_H
+
+/** @file
+ *
+ * Network interface management
+ *
+ */
+
+struct net_device;
+
+extern int ifopen ( struct net_device *netdev );
+extern void ifclose ( struct net_device *netdev );
+extern void ifstat ( struct net_device *netdev );
+
+#endif /* _USR_IFMGMT_H */
diff --git a/gpxe/src/include/usr/imgmgmt.h b/gpxe/src/include/usr/imgmgmt.h
new file mode 100644
index 00000000..438af003
--- /dev/null
+++ b/gpxe/src/include/usr/imgmgmt.h
@@ -0,0 +1,20 @@
+#ifndef _USR_IMGMGMT_H
+#define _USR_IMGMGMT_H
+
+/** @file
+ *
+ * Image management
+ *
+ */
+
+struct image;
+
+extern int imgfetch ( struct image *image, const char *uri_string,
+ int ( * image_register ) ( struct image *image ) );
+extern int imgload ( struct image *image );
+extern int imgexec ( struct image *image );
+extern struct image * imgautoselect ( void );
+extern void imgstat ( struct image *image );
+extern void imgfree ( struct image *image );
+
+#endif /* _USR_IMGMGMT_H */
diff --git a/gpxe/src/include/usr/iscsiboot.h b/gpxe/src/include/usr/iscsiboot.h
new file mode 100644
index 00000000..b17951d5
--- /dev/null
+++ b/gpxe/src/include/usr/iscsiboot.h
@@ -0,0 +1,6 @@
+#ifndef _USR_ISCSIBOOT_H
+#define _USR_ISCSIBOOT_H
+
+extern int iscsiboot ( const char *root_path );
+
+#endif /* _USR_ISCSIBOOT_H */
diff --git a/gpxe/src/include/usr/route.h b/gpxe/src/include/usr/route.h
new file mode 100644
index 00000000..fc855892
--- /dev/null
+++ b/gpxe/src/include/usr/route.h
@@ -0,0 +1,12 @@
+#ifndef _USR_ROUTE_H
+#define _USR_ROUTE_H
+
+/** @file
+ *
+ * Routing table management
+ *
+ */
+
+extern void route ( void );
+
+#endif /* _USR_ROUTE_H */