diff options
Diffstat (limited to 'src/include')
| -rw-r--r-- | src/include/background.h | 52 | ||||
| -rw-r--r-- | src/include/buffer.h | 96 | ||||
| -rw-r--r-- | src/include/compiler.h | 127 | ||||
| -rw-r--r-- | src/include/console.h | 83 | ||||
| -rw-r--r-- | src/include/dns.h | 4 | ||||
| -rw-r--r-- | src/include/errno.h | 141 | ||||
| -rw-r--r-- | src/include/etherboot.h | 59 | ||||
| -rw-r--r-- | src/include/igmp.h | 33 | ||||
| -rw-r--r-- | src/include/nmb.h | 2 | ||||
| -rw-r--r-- | src/include/pci_ids.h | 1 | ||||
| -rw-r--r-- | src/include/pxe.h | 956 | ||||
| -rw-r--r-- | src/include/pxe_api.h | 1696 | ||||
| -rw-r--r-- | src/include/pxe_export.h | 61 | ||||
| -rw-r--r-- | src/include/pxe_types.h | 126 | ||||
| -rw-r--r-- | src/include/tables.h | 214 | ||||
| -rw-r--r-- | src/include/tftp.h | 169 | ||||
| -rw-r--r-- | src/include/tftpcore.h | 33 | ||||
| -rw-r--r-- | src/include/vsprintf.h | 44 |
18 files changed, 2784 insertions, 1113 deletions
diff --git a/src/include/background.h b/src/include/background.h new file mode 100644 index 000000000..24cb3201f --- /dev/null +++ b/src/include/background.h @@ -0,0 +1,52 @@ +#ifndef BACKGROUND_H +#define BACKGROUND_H + +/** @file + * + * Background protocols + * + * Some protocols (e.g. ARP, IGMP) operate in the background; the + * upper layers are not aware of their operation. When an ARP query + * for the local station's IP address arrives, Etherboot must reply to + * it regardless of what other operations are currently in progress. + * + * Background protocols are called in two circumstances: when + * Etherboot is about to poll for a packet, and when Etherboot has + * received a packet that the upper layer (whatever that may currently + * be) isn't interested in. + * + */ + +#include "tables.h" +#include "ip.h" + +/** A background protocol */ +struct background { + /** Send method + * + * This method will be called whenever Etherboot is about to + * poll for a packet. The background protocol should use this + * method to send out any periodic transmissions that it may + * require. + */ + void ( *send ) ( unsigned long timestamp ); + /** Process method + * + * This method will be called whenever Etherboot has received + * a packet and doesn't know what to do with it. + */ + void ( *process ) ( unsigned long timestamp, unsigned short ptype, + struct iphdr *ip ); +}; + +/** A member of the background protocols table */ +#define __background __table ( background, 01 ) + +/* Functions in background.c */ + +extern void background_send ( unsigned long timestamp ); + +extern void background_process ( unsigned long timestamp, unsigned short ptype, + struct iphdr *ip ); + +#endif /* BACKGROUND_H */ diff --git a/src/include/buffer.h b/src/include/buffer.h index 0085c7d16..ac4c31481 100644 --- a/src/include/buffer.h +++ b/src/include/buffer.h @@ -1,41 +1,93 @@ #ifndef BUFFER_H #define BUFFER_H +#include "compiler.h" /* for doxygen */ #include "stdint.h" -/* - * "start" and "end" denote the real boundaries of the buffer. "fill" - * denotes the offset to the first free block in the buffer. (If the - * buffer is full, "fill" will equal ( end - start ) ). +/** @file + * + * Buffers for loading files. + * + * This file provides routines for filling a buffer with data received + * piecemeal, where the size of the data is not necessarily known in + * advance. + * + * Some protocols do not provide a mechanism for us to know the size + * of the file before we happen to receive a particular block + * (e.g. the final block in an MTFTP transfer). In addition, some + * protocols (all the multicast protocols plus any TCP-based protocol) + * can, in theory, provide the data in any order. + * + * Rather than requiring each protocol to implement its own equivalent + * of "dd" to arrange the data into well-sized pieces before handing + * off to the image loader, we provide these generic buffer functions + * which assemble a file into a single contiguous block. The whole + * block is then passed to the image loader. + * + * Example usage: + * + * @code + * + * struct buffer my_buffer; + * void *data; + * off_t offset; + * size_t len; + * + * // We have an area of memory [buf_start,buf_end) into which we want + * // to load a file, where buf_start and buf_end are physical addresses. + * buffer->start = buf_start; + * buffer->end = buf_end; + * init_buffer ( &buffer ); + * ... + * while ( get_file_block ( ... ) ) { + * // Downloaded block is stored in [data,data+len), and represents + * // the portion of the file at offsets [offset,offset+len) + * if ( ! fill_buffer ( &buffer, data, offset, len ) ) { + * // An error occurred + * return 0; + * } + * ... + * } + * ... + * // The whole file is now present at [buf_start,buf_start+filesize), + * // where buf_start is a physical address. The struct buffer can simply + * // be discarded; there is no done_buffer() call. + * + * @endcode + * + * For a description of the internal operation, see buffer.c. + * + */ + +/** + * A buffer + * + * #start and #end denote the real boundaries of the buffer, and are + * physical addresses. #fill denotes the offset to the first free + * block in the buffer. (If the buffer is full, #fill will equal + * #end-#start.) * */ struct buffer { - physaddr_t start; - physaddr_t end; - off_t fill; + physaddr_t start; /**< Start of buffer in memory */ + physaddr_t end; /**< End of buffer in memory */ + off_t fill; /**< Offset to first gap in buffer */ }; -/* - * Free blocks in the buffer start with a "tail byte". If non-zero, - * this byte indicates that the free block is the tail of the buffer, - * i.e. occupies all the remaining space up to the end of the buffer. - * When the tail byte is non-zero, it indicates that the remainder of - * the descriptor (the struct buffer_free_block) follows the tail - * byte. +/** + * A free block descriptor. * - * This scheme is necessary because we may end up with a tail that is - * smaller than a struct buffer_free_block. + * See buffer.c for a full description of the fields. * */ struct buffer_free_block { - char tail; - physaddr_t next_free; - physaddr_t end; + char tail; /**< Tail byte marker */ + char reserved[3]; /**< Padding */ + physaddr_t start; /**< Address of this free block */ + physaddr_t next; /**< Address of next free block */ + physaddr_t end; /**< End of this block */ } __attribute__ (( packed )); -/* This must be provided by the architecture-dependent load_buffer.c */ -extern struct buffer load_buffer; - /* Functions in buffer.c */ extern void init_buffer ( struct buffer *buffer ); diff --git a/src/include/compiler.h b/src/include/compiler.h index 4a7c48a1c..79781bc72 100644 --- a/src/include/compiler.h +++ b/src/include/compiler.h @@ -1,11 +1,30 @@ #ifndef COMPILER_H #define COMPILER_H -/* We export the symbol obj_OBJECT (OBJECT is defined on command-line) - * as a global symbol, so that the linker can drag in selected object - * files from the library using -u obj_OBJECT. +/* + * 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() and ASSERT(). * - * Not quite sure why cpp requires two levels of macro call in order + * 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 @@ -30,7 +49,9 @@ __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. * @@ -38,6 +59,56 @@ __asm__ ( ".equ\t" OBJECT_SYMBOL_STR ", 0" ); #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. + * + */ + +/** @def DBG2 + * + * Print a level 2 debugging message. + * + * As for DBG(). DBG2() takes effect only when the debugging level is + * 2 or greater. + * + */ + /* * If debug_OBJECT is set to a true value, the macro DBG(...) will * expand to printf(...) when compiling OBJECT, and the symbol @@ -67,8 +138,12 @@ __asm__ ( ".equ\tDEBUG_LEVEL, " DEBUG_SYMBOL_STR ); #define DBG2 DBG_PRINT #endif -/* - * ASSERT() macros +/** + * Assert a condition. + * + * If the condition is not true, a debug message will be printed. + * Assertions only take effect if the debug level is non-zero (see + * DBG()). * */ #define ASSERT(x) @@ -84,20 +159,35 @@ __asm__ ( ".equ\tDEBUG_LEVEL, " DEBUG_SYMBOL_STR ); } while (0) #endif -/* - * Commonly-used attributes. +/** Declare a data structure as packed. */ +#define PACKED __attribute__ (( packed )) + +/** + * Declare a variable or data structure as unused. * - * Note that __used can be used only for functions. If you have a - * static variable declaration that you want to force to be included, - * use __unused. + * Note that using #__unused on a static global variable (such as a + * table structure as mentioned in tables.h) is necessary in order to + * inhibit compiler warnings. * */ -#define PACKED __attribute__ (( packed )) #define __unused __attribute__ (( unused )) + +/** + * Declare a function as used. + * + * Necessary only if the function is called only from assembler code. + * You cannot use this attribute for static global variables; use + * #__unused instead. + * + */ #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 @@ -105,13 +195,16 @@ __asm__ ( ".equ\tDEBUG_LEVEL, " DEBUG_SYMBOL_STR ); * * Use as e.g. * - * struct { + * @code + * + * struct { * char rx_buf[NUM_RX_BUF][RX_BUF_SIZE]; * char tx_buf[TX_BUF_SIZE]; - * } my_static_data __shared; + * } my_static_data __shared; + * + * @endcode * */ - #define __shared __asm__ ( "_shared_bss" ) #endif /* ASSEMBLY */ diff --git a/src/include/console.h b/src/include/console.h index 1decb9c3b..9e13293ae 100644 --- a/src/include/console.h +++ b/src/include/console.h @@ -5,19 +5,94 @@ #include "vsprintf.h" #include "tables.h" -/* - * Consoles that cannot be used before their INIT_FN() has completed - * should set disabled = 1 initially. This allows other console - * devices to still be used to print out early debugging messages. +/** @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 INIT_FN() 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(), getchar() and iskey() methods will + * not be called while #disabled==1. Typically the + * console's initialisation functions (called via INIT_FN()) + * 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 ); + + /** 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 ( console, 01 ) /* Function prototypes */ diff --git a/src/include/dns.h b/src/include/dns.h index 5b8b81f13..33ee73fe5 100644 --- a/src/include/dns.h +++ b/src/include/dns.h @@ -70,12 +70,12 @@ struct dns_rr_info { } __attribute__ (( packed )); struct dns_rr_info_a { - struct dns_rr_info; + struct dns_rr_info info; struct in_addr in_addr; } __attribute__ (( packed )); struct dns_rr_info_cname { - struct dns_rr_info; + struct dns_rr_info info; char cname[0]; } __attribute__ (( packed )); diff --git a/src/include/errno.h b/src/include/errno.h new file mode 100644 index 000000000..e122d9c39 --- /dev/null +++ b/src/include/errno.h @@ -0,0 +1,141 @@ +#ifndef ERRNO_H +#define ERRNO_H + +/** @file + * + * Error codes + * + */ + +/* PXE error codes are determined by the PXE specification */ + +/* Generic errors */ +#define PXENV_STATUS_SUCCESS 0x00 +#define PXENV_STATUS_FAILURE 0x01 +#define PXENV_STATUS_BAD_FUNC 0x02 +#define PXENV_STATUS_UNSUPPORTED 0x03 +#define PXENV_STATUS_KEEP_UNDI 0x04 +#define PXENV_STATUS_KEEP_ALL 0x05 +#define PXENV_STATUS_OUT_OF_RESOURCES 0x06 + +/* ARP errors (0x10 to 0x1f) */ +#define PXENV_STATUS_ARP_TIMEOUT 0x11 + +/* Base-Code state errors */ +#define PXENV_STATUS_UDP_CLOSED 0x18 +#define PXENV_STATUS_UDP_OPEN 0x19 +#define PXENV_STATUS_TFTP_CLOSED 0x1a +#define PXENV_STATUS_TFTP_OPEN 0x1b + +/* BIOS/system errors (0x20 to 0x2f) */ +#define PXENV_STATUS_MCOPY_PROBLEM 0x20 +#define PXENV_STATUS_BIS_INTEGRITY_FAILURE 0x21 +#define PXENV_STATUS_BIS_VALIDATE_FAILURE 0x22 +#define PXENV_STATUS_BIS_INIT_FAILURE 0x23 +#define PXENV_STATUS_BIS_SHUTDOWN_FAILURE 0x24 +#define PXENV_STATUS_BIS_GBOA_FAILURE 0x25 +#define PXENV_STATUS_BIS_FREE_FAILURE 0x26 +#define PXENV_STATUS_BIS_GSI_FAILURE 0x27 +#define PXENV_STATUS_BIS_BAD_CKSUM 0x28 + +/* TFTP/MTFTP errors (0x30 to 0x3f) */ +#define PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS 0x30 +#define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x32 +#define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x33 +#define PXENV_STATUS_TFTP_READ_TIMEOUT 0x35 +#define PXENV_STATUS_TFTP_ERROR_OPCODE 0x36 +#define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION 0x38 +#define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION 0x39 +#define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES 0x3a +#define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x3b +#define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x3c +#define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x3d +#define PXENV_STATUS_TFTP_NO_FILESIZE 0x3e +#define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE 0x3f + +/* Reserved errors 0x40 to 0x4f) */ + +/* DHCP/BOOTP errors (0x50 to 0x5f) */ +#define PXENV_STATUS_DHCP_TIMEOUT 0x51 +#define PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x52 +#define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x53 +#define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x54 + +/* Driver errors (0x60 to 0x6f) */ +#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x60 +#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x61 +#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x62 +#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x63 +#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x64 +#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x65 +#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x66 +#define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x67 +#define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM 0x68 +#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x69 +#define PXENV_STATUS_UNDI_INVALID_STATE 0x6a +#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x6b +#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x6c + +/* ROM and NBP bootstrap errors (0x70 to 0x7f) */ +#define PXENV_STATUS_BSTRAP_PROMPT_MENU 0x74 +#define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x76 +#define PXENV_STATUS_BSTRAP_MISSING_LIST 0x77 +#define PXENV_STATUS_BSTRAP_NO_RESPONSE 0x78 +#define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x79 + +/* Environment NBP errors (0x80 to 0x8f) */ + +/* Reserved errors (0x90 to 0x9f) */ + +/* Miscellaneous errors (0xa0 to 0xaf) */ +#define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE 0xa0 +#define PXENV_STATUS_BINL_NO_PXE_SERVER 0xa1 +#define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE 0xa2 +#define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE 0xa3 + +/* BUSD errors (0xb0 to 0xbf) */ +#define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED 0xb0 + +/* Loader errors (0xc0 to 0xcf) */ +#define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY 0xc0 +#define PXENV_STATUS_LOADER_NO_BC_ROMID 0xc1 +#define PXENV_STATUS_LOADER_BAD_BC_ROMID 0xc2 +#define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE 0xc3 +#define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0xc4 +#define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0xc5 +#define PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE 0xc6 +#define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0xc8 +#define PXENV_STATUS_LOADER_NO_PXENV_STRUCT 0xc9 +#define PXENV_STATUS_LOADER_UNDI_START 0xca +#define PXENV_STATUS_LOADER_BC_START 0xcb + +/* + * The range 0xd0 to 0xff is defined as "Vendor errors" by the PXE + * spec. We place all our Etherboot-specific errors in this range. + * We also define some generic errors as aliases to the PXE errors. + * + */ + +#define ENOERR 0x00 +#define ENOMEM PXENV_STATUS_OUT_OF_RESOURCES +#define EBADIMG 0xd0 +#define EIMGRET 0xd1 +#define ETIMEDOUT 0xd2 +#define EINVAL 0xd3 + +/* Data structures and declarations */ + +#include "tables.h" + +extern int errno; + +extern const char * strerror ( int errno ); + +struct errortab { + int errno; + const char *text; +}; + +#define __errortab __table(errortab,01) + +#endif /* ERRNO_H */ diff --git a/src/include/etherboot.h b/src/include/etherboot.h index e61a711ff..b9546c043 100644 --- a/src/include/etherboot.h +++ b/src/include/etherboot.h @@ -1,6 +1,26 @@ #ifndef ETHERBOOT_H #define ETHERBOOT_H +/* + * Standard includes that we always want + * + */ + +#include "compiler.h" +#include "stddef.h" +#include "stdint.h" + + +/* + * 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. + * + */ + + #include <stdarg.h> #include "osdep.h" @@ -110,16 +130,11 @@ enum { MAX_ARP }; -#define IGMP_SERVER 0 -#define MAX_IGMP IGMP_SERVER+1 - #define RARP_REQUEST 3 #define RARP_REPLY 4 #include "in.h" -#define MULTICAST_MASK 0xF0000000 -#define MULTICAST_NETWORK 0xE0000000 /* Helper macros used to identify when DHCP options are valid/invalid in/outside of encapsulation */ #define NON_ENCAP_OPT in_encapsulated_options == 0 && @@ -134,7 +149,6 @@ enum { #include "udp.h" #include "tcp.h" #include "bootp.h" -#include "tftp.h" #include "igmp.h" #include "nfs.h" #include "console.h" @@ -145,12 +159,7 @@ struct arptable_t { uint8_t node[6]; } PACKED; -struct igmptable_t { - in_addr group; - unsigned long time; -} PACKED; - -#define KERNEL_BUF (BOOTP_DATA_ADDR->bootp_reply.bp_file) +#define KERNEL_BUF (bootp_data.bootp_reply.bp_file) #define FLOPPY_BOOT_LOCATION 0x7c00 @@ -195,19 +204,13 @@ int tcp_reset(struct iphdr *ip); typedef int (*reply_t)(int ival, void *ptr, unsigned short ptype, struct iphdr *ip, struct udphdr *udp, struct tcphdr *tcp); extern int await_reply P((reply_t reply, int ival, void *ptr, long timeout)); extern int decode_rfc1533 P((unsigned char *, unsigned int, unsigned int, int)); -extern void join_group(int slot, unsigned long group); -extern void leave_group(int slot); #define RAND_MAX 2147483647L extern uint16_t ipchksum P((const void *ip, unsigned long len)); extern uint16_t add_ipchksums P((unsigned long offset, uint16_t sum, uint16_t new)); extern int32_t random P((void)); extern long rfc2131_sleep_interval P((long base, int exp)); -extern long rfc1112_sleep_interval P((long base, int exp)); extern void cleanup P((void)); -/* config.c */ -extern void print_config(void); - /* osloader.c */ /* Be careful with sector_t it is an unsigned long long on x86 */ typedef uint64_t sector_t; @@ -271,15 +274,6 @@ extern int elf_start(unsigned long machine, unsigned long entry, unsigned long p extern unsigned long currticks P((void)); extern void exit P((int status)); -/* serial.c */ -extern int serial_getc P((void)); -extern void serial_putc P((int)); -extern int serial_ischar P((void)); -extern int serial_init P((void)); -extern void serial_fini P((void)); - -/* floppy.c */ -extern int bootdisk P((int dev,int part)); /*************************************************************************** External variables @@ -288,10 +282,11 @@ External variables extern struct rom_info rom; extern char *hostname; extern int hostnamelen; +extern unsigned char *addparam; +extern int addparamlen; extern jmp_buf restart_etherboot; extern int url_port; extern struct arptable_t arptable[MAX_ARP]; -extern struct igmptable_t igmptable[MAX_IGMP]; #ifdef IMAGE_MENU extern int menutmo,menudefault; extern unsigned char *defparams; @@ -309,14 +304,6 @@ extern int freebsd_howto; extern char freebsd_kernel_env[FREEBSD_KERNEL_ENV_SIZE]; #endif -/* bootmenu.c */ - -/* osloader.c */ - -/* created by linker */ -extern char _virt_start[], _text[], _etext[], _text16[], _etext16[]; -extern char _data[], _edata[], _bss[], _ebss[], _end[]; - /* * Local variables: diff --git a/src/include/igmp.h b/src/include/igmp.h index 2235d6c66..48753eab5 100644 --- a/src/include/igmp.h +++ b/src/include/igmp.h @@ -1,5 +1,8 @@ -#ifndef _IGMP_H -#define _IGMP_H +#ifndef IGMP_H +#define IGMP_H + +#include "stdint.h" +#include "in.h" #define IGMP_QUERY 0x11 #define IGMPv1_REPORT 0x12 @@ -7,11 +10,19 @@ #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; - in_addr group; + 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 */ @@ -20,4 +31,12 @@ struct igmp_ip_t { /* Format of an igmp ip packet */ struct igmp igmp; } PACKED; -#endif /* _IGMP_H */ +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/src/include/nmb.h b/src/include/nmb.h index 695f8e08f..7948d9e48 100644 --- a/src/include/nmb.h +++ b/src/include/nmb.h @@ -14,7 +14,7 @@ #define NBNS_UDP_PORT 137 struct dns_rr_info_nb { - struct dns_rr_info; + struct dns_rr_info info; uint16_t nb_flags; struct in_addr nb_address; } __attribute__ (( packed )); diff --git a/src/include/pci_ids.h b/src/include/pci_ids.h index bcf4c3cd8..a853d4dcb 100644 --- a/src/include/pci_ids.h +++ b/src/include/pci_ids.h @@ -319,6 +319,7 @@ #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 diff --git a/src/include/pxe.h b/src/include/pxe.h index 48f555094..f8e2de79b 100644 --- a/src/include/pxe.h +++ b/src/include/pxe.h @@ -1,895 +1,59 @@ -/* - * pxe.h for Etherboot. - * - * PXE is technically specified only for i386, but there's no reason - * why we shouldn't make the API available for other architectures, - * provided that someone wants to write the shim that allows an - * external program to call pxe_api_call(). - * - * We stick with Intel's data structure definitions as far as possible - * on other architectures. Generally the only i386-specific stuff is - * related to addressing: real-mode segment:offset addresses, segment - * selectors, segment descriptors etc. We allow an architecture- - * specific header to define these types, then build the PXE - * structures. Note that we retain the names from the PXE - * specification document (e.g. SEGOFF16_t) even if the architecture - * in question doesn't represent a SEGOFF16_t as anything resembling a - * 16-bit segment:offset address. This is done in order to keep the - * structure definitions as close as possible to those in the spec, to - * minimise confusion. - * - * This file derives from several originals. One is pxe.h from - * FreeBSD. Another is general.h86 from netboot. The original - * copyright notices are reproduced below. This entire file is - * licensed under the GPL; the netboot code is GPL anyway and the - * FreeBSD code allows us to relicense under the GPL provided that we - * retain the FreeBSD copyright notice. This is my understanding, - * anyway. Other portions are my own and therefore Copyright (C) 2004 - * Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - #ifndef PXE_H #define PXE_H -/* Include architecture-specific PXE data types - * - * May define SEGOFF16_t, SEGDESC_t and SEGSEL_t. These should be - * #defines to underlying * types. May also define - * IS_NULL_SEGOFF16(segoff16), SEGOFF16_TO_PTR(segoff16) and - * PTR_TO_SEGOFF16(ptr,segoff16) - */ -#ifndef PXE_TYPES_H -#include <pxe_types.h> -#endif - -/* Defaults in case pxe_types.h did not define a type. These are - * placeholder structures just to make the code compile. - */ -#ifndef SEGOFF16_t -#define SEGOFF16_t void* -#endif - -#ifndef IS_NULL_SEGOFF16 -#define IS_NULL_SEGOFF16(segoff16) ( (segoff16) == NULL ) -#endif - -#ifndef SEGOFF16_TO_PTR -#define SEGOFF16_TO_PTR(segoff16) (segoff16) -#endif - -#ifndef PTR_TO_SEGOFF16 -#define PTR_TO_SEGOFF16(ptr,segoff16) (segoff16) = (ptr); -#endif - -#ifndef SEGDESC_t -#define SEGDESC_t void -#endif - -#ifndef SEGSEL_t -#define SEGSEL_t void -#endif - -/***************************************************************************** - * The following portion of this file is derived from FreeBSD's pxe.h. - * Do not remove the copyright notice below. - ***************************************************************************** - */ - -/* - * Copyright (c) 2000 Alfred Perlstein <alfred@freebsd.org> - * All rights reserved. - * Copyright (c) 2000 Paul Saab <ps@freebsd.org> - * All rights reserved. - * Copyright (c) 2000 John Baldwin <jhb@freebsd.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/boot/i386/libi386/pxe.h,v 1.4.2.2 2000/09/10 02:52:18 ps Exp $ - */ - -/* - * The typedefs and structures declared in this file - * clearly violate style(9), the reason for this is to conform to the - * typedefs/structure-names used in the Intel literature to avoid confusion. - * - * It's for your own good. :) - */ - -/* It seems that intel didn't think about ABI, - * either that or 16bit ABI != 32bit ABI (which seems reasonable) - * I have to thank Intel for the hair loss I incurred trying to figure - * out why PXE was mis-reading structures I was passing it (at least - * from my point of view) - * - * Solution: use gcc's '__attribute__ ((packed))' to correctly align - * structures passed into PXE - * Question: does this really work for PXE's expected ABI? - */ -#ifndef PACKED -#define PACKED __attribute__ ((packed)) -#endif - -#define S_SIZE(s) s, sizeof(s) - 1 - -#define IP_STR "%d.%d.%d.%d" -#define IP_ARGS(ip) \ - (int)(ip >> 24) & 0xff, (int)(ip >> 16) & 0xff, \ - (int)(ip >> 8) & 0xff, (int)ip & 0xff - -#define MAC_STR "%02x:%02x:%02x:%02x:%02x:%02x" -#define MAC_ARGS(mac) \ - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] - -typedef uint16_t PXENV_EXIT_t; -typedef uint16_t PXENV_STATUS_t; -typedef uint32_t IP4_t; -typedef uint32_t ADDR32_t; -/* It seems as though UDP_PORT_t is in network order, although I can't - * find anything in the spec to back this up. (Michael Brown) - */ -typedef uint16_t UDP_PORT_t; - -#define MAC_ADDR_LEN 16 -typedef uint8_t MAC_ADDR[MAC_ADDR_LEN]; - -/* PXENV+ */ -typedef struct { - uint8_t Signature[6]; /* 'PXENV+' */ - uint16_t Version; /* MSB = major, LSB = minor */ - uint8_t Length; /* structure length */ - uint8_t Checksum; /* checksum pad */ - SEGOFF16_t RMEntry; /* SEG:OFF to PXE entry point */ - /* don't use PMOffset and PMSelector (from the 2.1 PXE manual) */ - uint32_t PMOffset; /* Protected mode entry */ - SEGSEL_t PMSelector; /* Protected mode selector */ - SEGSEL_t StackSeg; /* Stack segment address */ - uint16_t StackSize; /* Stack segment size (bytes) */ - SEGSEL_t BC_CodeSeg; /* BC Code segment address */ - uint16_t BC_CodeSize; /* BC Code segment size (bytes) */ - SEGSEL_t BC_DataSeg; /* BC Data segment address */ - uint16_t BC_DataSize; /* BC Data segment size (bytes) */ - SEGSEL_t UNDIDataSeg; /* UNDI Data segment address */ - uint16_t UNDIDataSize; /* UNDI Data segment size (bytes) */ - SEGSEL_t UNDICodeSeg; /* UNDI Code segment address */ - uint16_t UNDICodeSize; /* UNDI Code segment size (bytes) */ - SEGOFF16_t PXEPtr; /* SEG:OFF to !PXE struct, - only present when Version > 2.1 */ -} PACKED pxenv_t; - -/* !PXE */ -typedef struct { - uint8_t Signature[4]; - uint8_t StructLength; - uint8_t StructCksum; - uint8_t StructRev; - uint8_t reserved_1; - SEGOFF16_t UNDIROMID; - SEGOFF16_t BaseROMID; - SEGOFF16_t EntryPointSP; - SEGOFF16_t EntryPointESP; - SEGOFF16_t StatusCallout; - uint8_t reserved_2; - uint8_t SegDescCn; - SEGSEL_t FirstSelector; - SEGDESC_t Stack; - SEGDESC_t UNDIData; - SEGDESC_t UNDICode; - SEGDESC_t UNDICodeWrite; - SEGDESC_t BC_Data; - SEGDESC_t BC_Code; - SEGDESC_t BC_CodeWrite; -} PACKED pxe_t; - -#define PXENV_START_UNDI 0x0000 -typedef struct { - PXENV_STATUS_t Status; - uint16_t ax; - uint16_t bx; - uint16_t dx; - uint16_t di; - uint16_t es; -} PACKED t_PXENV_START_UNDI; - -#define PXENV_UNDI_STARTUP 0x0001 -typedef struct { - PXENV_STATUS_t Status; -} PACKED t_PXENV_UNDI_STARTUP; - -#define PXENV_UNDI_CLEANUP 0x0002 -typedef struct { - PXENV_STATUS_t Status; -} PACKED t_PXENV_UNDI_CLEANUP; - -#define PXENV_UNDI_INITIALIZE 0x0003 -typedef struct { - PXENV_STATUS_t Status; - ADDR32_t ProtocolIni; /* Phys addr of a copy of the driver module */ - uint8_t reserved[8]; -} PACKED t_PXENV_UNDI_INITIALIZE; - - -#define MAXNUM_MCADDR 8 -typedef struct { - uint16_t MCastAddrCount; - MAC_ADDR McastAddr[MAXNUM_MCADDR]; -} PACKED t_PXENV_UNDI_MCAST_ADDRESS; - -#define PXENV_UNDI_RESET_ADAPTER 0x0004 -typedef struct { - PXENV_STATUS_t Status; - t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf; -} PACKED t_PXENV_UNDI_RESET_ADAPTER; - -#define PXENV_UNDI_SHUTDOWN 0x0005 -typedef struct { - PXENV_STATUS_t Status; -} PACKED t_PXENV_UNDI_SHUTDOWN; - -#define PXENV_UNDI_OPEN 0x0006 -typedef struct { - PXENV_STATUS_t Status; - uint16_t OpenFlag; - uint16_t PktFilter; -# define FLTR_DIRECTED 0x0001 -# define FLTR_BRDCST 0x0002 -# define FLTR_PRMSCS 0x0003 -# define FLTR_SRC_RTG 0x0004 - - t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf; -} PACKED t_PXENV_UNDI_OPEN; - -#define PXENV_UNDI_CLOSE 0x0007 -typedef struct { - PXENV_STATUS_t Status; -} PACKED t_PXENV_UNDI_CLOSE; - -#define PXENV_UNDI_TRANSMIT 0x0008 -typedef struct { - PXENV_STATUS_t Status; - uint8_t Protocol; -# define P_UNKNOWN 0 -# define P_IP 1 -# define P_ARP 2 -# define P_RARP 3 - - uint8_t XmitFlag; -# define XMT_DESTADDR 0x0000 -# define XMT_BROADCAST 0x0001 - - SEGOFF16_t DestAddr; - SEGOFF16_t TBD; - uint32_t Reserved[2]; -} PACKED t_PXENV_UNDI_TRANSMIT; - -#define MAX_DATA_BLKS 8 -typedef struct { - uint16_t ImmedLength; - SEGOFF16_t Xmit; - uint16_t DataBlkCount; - struct DataBlk { - uint8_t TDPtrType; - uint8_t TDRsvdByte; - uint16_t TDDataLen; - SEGOFF16_t TDDataPtr; - } DataBlock[MAX_DATA_BLKS]; -} PACKED t_PXENV_UNDI_TBD; - -#define PXENV_UNDI_SET_MCAST_ADDRESS 0x0009 -typedef struct { - PXENV_STATUS_t Status; - t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf; -} PACKED t_PXENV_UNDI_SET_MCAST_ADDRESS; - -#define PXENV_UNDI_SET_STATION_ADDRESS 0x000A -typedef struct { - PXENV_STATUS_t Status; - MAC_ADDR StationAddress; /* Temp MAC addres to use */ -} PACKED t_PXENV_UNDI_SET_STATION_ADDRESS; - -#define PXENV_UNDI_SET_PACKET_FILTER 0x000B -typedef struct { - PXENV_STATUS_t Status; - uint8_t filter; /* see UNDI_OPEN (0x0006) */ -} PACKED t_PXENV_UNDI_SET_PACKET_FILTER; - -#define PXENV_UNDI_GET_INFORMATION 0x000C -typedef struct { - PXENV_STATUS_t Status; - uint16_t BaseIo; /* Adapter base I/O address */ - uint16_t IntNumber; /* Adapter IRQ number */ - uint16_t MaxTranUnit; /* Adapter maximum transmit unit */ - uint16_t HwType; /* Type of protocol at the hardware addr */ -# define ETHER_TYPE 1 -# define EXP_ETHER_TYPE 2 -# define IEEE_TYPE 6 -# define ARCNET_TYPE 7 - - uint16_t HwAddrLen; /* Length of hardware address */ - MAC_ADDR CurrentNodeAddress; /* Current hardware address */ - MAC_ADDR PermNodeAddress; /* Permanent hardware address */ - SEGSEL_t ROMAddress; /* Real mode ROM segment address */ - uint16_t RxBufCt; /* Receive queue length */ - uint16_t TxBufCt; /* Transmit queue length */ -} PACKED t_PXENV_UNDI_GET_INFORMATION; - -#define PXENV_UNDI_GET_STATISTICS 0x000D -typedef struct { - PXENV_STATUS_t Status; - uint32_t XmitGoodFrames; /* Number of successful transmissions */ - uint32_t RcvGoodFrames; /* Number of good frames received */ - uint32_t RcvCRCErrors; /* Number of frames with CRC errors */ - uint32_t RcvResourceErrors; /* Number of frames dropped */ -} PACKED t_PXENV_UNDI_GET_STATISTICS; - -#define PXENV_UNDI_CLEAR_STATISTICS 0x000E -typedef struct { - PXENV_STATUS_t Status; -} PACKED t_PXENV_UNDI_CLEAR_STATISTICS; - -#define PXENV_UNDI_INITIATE_DIAGS 0x000F -typedef struct { - PXENV_STATUS_t Status; -} PACKED t_PXENV_UNDI_INITIATE_DIAGS; - -#define PXENV_UNDI_FORCE_INTERRUPT 0x0010 -typedef struct { - PXENV_STATUS_t Status; -} PACKED t_PXENV_UNDI_FORCE_INTERRUPT; - -#define PXENV_UNDI_GET_MCAST_ADDRESS 0x0011 -typedef struct { - PXENV_STATUS_t Status; - IP4_t InetAddr; /* IP mulicast address */ - MAC_ADDR MediaAddr; /* MAC multicast address */ -} PACKED t_PXENV_UNDI_GET_MCAST_ADDRESS; - -#define PXENV_UNDI_GET_NIC_TYPE 0x0012 -typedef struct { - PXENV_STATUS_t Status; - uint8_t NicType; /* Type of NIC */ -# define PCI_NIC 2 -# define PnP_NIC 3 -# define CardBus_NIC 4 - - union { - struct { - uint16_t Vendor_ID; - uint16_t Dev_ID; - uint8_t Base_Class; - uint8_t Sub_Class; - uint8_t Prog_Intf; - uint8_t Rev; - uint16_t BusDevFunc; - uint16_t SubVendor_ID; - uint16_t SubDevice_ID; - } pci, cardbus; - struct { - uint32_t EISA_Dev_ID; - uint8_t Base_Class; - uint8_t Sub_Class; - uint8_t Prog_Intf; - uint16_t CardSelNum; - } pnp; - } info; -} PACKED t_PXENV_UNDI_GET_NIC_TYPE; - -#define PXENV_UNDI_GET_IFACE_INFO 0x0013 -typedef struct { - PXENV_STATUS_t Status; - uint8_t IfaceType[16]; /* Name of MAC type in ASCII. */ - uint32_t LinkSpeed; /* Defined in NDIS 2.0 spec */ - uint32_t ServiceFlags; /* Defined in NDIS 2.0 spec */ - uint32_t Reserved[4]; /* must be 0 */ -} PACKED t_PXENV_UNDI_GET_IFACE_INFO; - -#define PXENV_UNDI_ISR 0x0014 -typedef struct { - PXENV_STATUS_t Status; - uint16_t FuncFlag; /* PXENV_UNDI_ISR_OUT_xxx */ - uint16_t BufferLength; /* Length of Frame */ - uint16_t FrameLength; /* Total length of reciever frame */ - uint16_t FrameHeaderLength; /* Length of the media header in Frame */ - SEGOFF16_t Frame; /* receive buffer */ - uint8_t ProtType; /* Protocol type */ - uint8_t PktType; /* Packet Type */ -# define PXENV_UNDI_ISR_IN_START 1 -# define PXENV_UNDI_ISR_IN_PROCESS 2 -# define PXENV_UNDI_ISR_IN_GET_NEXT 3 - - /* one of these will be returned for PXENV_UNDI_ISR_IN_START */ -# define PXENV_UNDI_ISR_OUT_OURS 0 -# define PXENV_UNDI_ISR_OUT_NOT_OURS 1 - - /* - * one of these will bre returnd for PXEND_UNDI_ISR_IN_PROCESS - * and PXENV_UNDI_ISR_IN_GET_NEXT - */ -# define PXENV_UNDI_ISR_OUT_DONE 0 -# define PXENV_UNDI_ISR_OUT_TRANSMIT 2 -# define PXENV_UNDI_ISR_OUT_RECEIVE 3 -# define PXENV_UNDI_ISR_OUT_BUSY 4 -} PACKED t_PXENV_UNDI_ISR; - -#define PXENV_STOP_UNDI 0x0015 -typedef struct { - PXENV_STATUS_t Status; -} PACKED t_PXENV_STOP_UNDI; - -#define PXENV_TFTP_OPEN 0x0020 -typedef struct { - PXENV_STATUS_t Status; - IP4_t ServerIPAddress; - IP4_t GatewayIPAddress; - uint8_t FileName[128]; - UDP_PORT_t TFTPPort; - uint16_t PacketSize; -} PACKED t_PXENV_TFTP_OPEN; - -#define PXENV_TFTP_CLOSE 0x0021 -typedef struct { - PXENV_STATUS_t Status; -} PACKED t_PXENV_TFTP_CLOSE; - -#define PXENV_TFTP_READ 0x0022 -typedef struct { - PXENV_STATUS_t Status; - uint16_t PacketNumber; - uint16_t BufferSize; - SEGOFF16_t Buffer; -} PACKED t_PXENV_TFTP_READ; - -#define PXENV_TFTP_READ_FILE 0x0023 -typedef struct { - PXENV_STATUS_t Status; - uint8_t FileName[128]; - uint32_t BufferSize; - ADDR32_t Buffer; - IP4_t ServerIPAddress; - IP4_t GatewayIPAdress; - IP4_t McastIPAdress; - UDP_PORT_t TFTPClntPort; - UDP_PORT_t TFTPSrvPort; - uint16_t TFTPOpenTimeOut; - uint16_t TFTPReopenDelay; -} PACKED t_PXENV_TFTP_READ_FILE; - -#define PXENV_TFTP_GET_FSIZE 0x0025 -typedef struct { - PXENV_STATUS_t Status; - IP4_t ServerIPAddress; - IP4_t GatewayIPAdress; - uint8_t FileName[128]; - uint32_t FileSize; -} PACKED t_PXENV_TFTP_GET_FSIZE; - -#define PXENV_UDP_OPEN 0x0030 -typedef struct { - PXENV_STATUS_t Status; - IP4_t src_ip; /* IP address of this station */ -} PACKED t_PXENV_UDP_OPEN; - -#define PXENV_UDP_CLOSE 0x0031 -typedef struct { - PXENV_STATUS_t Status; -} PACKED t_PXENV_UDP_CLOSE; - -#define PXENV_UDP_READ 0x0032 -typedef struct { - PXENV_STATUS_t Status; - IP4_t src_ip; /* IP of sender */ - IP4_t dest_ip; /* Only accept packets sent to this IP */ - UDP_PORT_t s_port; /* UDP source port of sender */ - UDP_PORT_t d_port; /* Only accept packets sent to this port */ - uint16_t buffer_size; /* Size of the packet buffer */ - SEGOFF16_t buffer; /* SEG:OFF to the packet buffer */ -} PACKED t_PXENV_UDP_READ; - -#define PXENV_UDP_WRITE 0x0033 -typedef struct { - PXENV_STATUS_t Status; - IP4_t ip; /* dest ip addr */ - IP4_t gw; /* ip gateway */ - UDP_PORT_t src_port; /* source udp port */ - UDP_PORT_t dst_port; /* destination udp port */ - uint16_t buffer_size; /* Size of the packet buffer */ - SEGOFF16_t buffer; /* SEG:OFF to the packet buffer */ -} PACKED t_PXENV_UDP_WRITE; - -#define PXENV_UNLOAD_STACK 0x0070 -typedef struct { - PXENV_STATUS_t Status; - uint8_t reserved[10]; -} PACKED t_PXENV_UNLOAD_STACK; - - -#define PXENV_GET_CACHED_INFO 0x0071 -typedef struct { - PXENV_STATUS_t Status; - uint16_t PacketType; /* type (defined right here) */ -# define PXENV_PACKET_TYPE_DHCP_DISCOVER 1 -# define PXENV_PACKET_TYPE_DHCP_ACK 2 -# define PXENV_PACKET_TYPE_BINL_REPLY 3 - uint16_t BufferSize; /* max to copy, leave at 0 for pointer */ - SEGOFF16_t Buffer; /* copy to, leave at 0 for pointer */ - uint16_t BufferLimit; /* max size of buffer in BC dataseg ? */ -} PACKED t_PXENV_GET_CACHED_INFO; - - -/* structure filled in by PXENV_GET_CACHED_INFO - * (how we determine which IP we downloaded the initial bootstrap from) - * words can't describe... - */ -typedef struct { - uint8_t opcode; -# define BOOTP_REQ 1 -# define BOOTP_REP 2 - uint8_t Hardware; /* hardware type */ - uint8_t Hardlen; /* hardware addr len */ - uint8_t Gatehops; /* zero it */ - uint32_t ident; /* random number chosen by client */ - uint16_t seconds; /* seconds since did initial bootstrap */ - uint16_t Flags; /* seconds since did initial bootstrap */ -# define BOOTP_BCAST 0x8000 /* ? */ - IP4_t cip; /* Client IP */ - IP4_t yip; /* Your IP */ - IP4_t sip; /* IP to use for next boot stage */ - IP4_t gip; /* Relay IP ? */ - MAC_ADDR CAddr; /* Client hardware address */ - uint8_t Sname[64]; /* Server's hostname (Optional) */ - uint8_t bootfile[128]; /* boot filename */ - union { -# if 1 -# define BOOTP_DHCPVEND 1024 /* DHCP extended vendor field size */ -# else -# define BOOTP_DHCPVEND 312 /* DHCP standard vendor field size */ -# endif - uint8_t d[BOOTP_DHCPVEND]; /* raw array of vendor/dhcp options */ - struct { - uint8_t magic[4]; /* DHCP magic cookie */ -# ifndef VM_RFC1048 -# define VM_RFC1048 0x63825363L /* ? */ -# endif - uint32_t flags; /* bootp flags/opcodes */ - uint8_t pad[56]; /* I don't think intel knows what a - union does... */ - } v; - } vendor; -} PACKED BOOTPLAYER; - -#define PXENV_RESTART_TFTP 0x0073 -#define t_PXENV_RESTART_TFTP t_PXENV_TFTP_READ_FILE - -#define PXENV_START_BASE 0x0075 -typedef struct { - PXENV_STATUS_t Status; -} PACKED t_PXENV_START_BASE; - -#define PXENV_STOP_BASE 0x0076 -typedef struct { - PXENV_STATUS_t Status; -} PACKED t_PXENV_STOP_BASE; - -/***************************************************************************** - * The following portion of this file is derived from netboot's - * general.h86. Do not remove the copyright notice below. - ***************************************************************************** - */ - -/* - * general.h86 - Common PXE definitions - * - * Copyright (C) 2003 Gero Kuhlmann <gero@gkminix.han.de> - * - * 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. - * - * $Id$ - */ - -/* - ************************************************************************** - * - * This file contains the Preboot API common definitions as - * per Intels PXE specification version 2.0. - * - * Updated to comply with PXE specification version 2.1 by Michael Brown. - * - ************************************************************************** - * - * Result codes returned in AX by a PXENV API service: - */ -#define PXENV_EXIT_SUCCESS 0x0000 -#define PXENV_EXIT_FAILURE 0x0001 - - - -/* - ************************************************************************** - * - * CPU types (defined in WfM 1.1): - */ -#define PXENV_CPU_X86 0 -#define PXENV_CPU_ALPHA 1 -#define PXENV_CPU_PPC 2 - - - -/* - ************************************************************************** - * - * Bus types (defined in WfM 1.1): - */ -#define PXENV_BUS_ISA 0 -#define PXENV_BUS_EISA 1 -#define PXENV_BUS_MCA 2 -#define PXENV_BUS_PCI 3 -#define PXENV_BUS_VESA 4 -#define PXENV_BUS_PCMCIA 5 - - - -/* - ************************************************************************** - * - * Status codes returned in the status word of the PXENV API parameter - * structure. Some of these codes are also used to return status - * information from a boot image loader back to the bootrom. - */ - -/* Generic API errors that are reported by the loader */ -#define PXENV_STATUS_SUCCESS 0x00 -#define PXENV_STATUS_FAILURE 0x01 /* general failure */ -#define PXENV_STATUS_BAD_FUNC 0x02 /* invalid function number */ -#define PXENV_STATUS_UNSUPPORTED 0x03 /* not yet supported */ -#define PXENV_STATUS_KEEP_UNDI 0x04 /* keep UNDI in memory */ -#define PXENV_STATUS_KEEP_ALL 0x05 /* keep everything in memory */ -#define PXENV_STATUS_OUT_OF_RESOURCES 0x06 /* also keep everything */ - -/* ARP/UDP errors (0x10 to 0x1F) */ -#define PXENV_STATUS_ARP_CANCELED 0x10 /* ARP canceled by keystroke */ -#define PXENV_STATUS_ARP_TIMEOUT 0x11 /* ARP timeout */ -#define PXENV_STATUS_UDP_CLOSED 0x18 /* UDP closed */ -#define PXENV_STATUS_UDP_OPEN 0x19 /* UDP already open */ -#define PXENV_STATUS_TFTP_CLOSED 0x1A /* TFTP closed */ -#define PXENV_STATUS_TFTP_OPEN 0x1B /* TFTP already opened */ - -/* BIOS/system errors (0x20 to 0x2F) */ -#define PXENV_STATUS_MCOPY_PROBLEM 0x20 /* can't copy into memory */ - -/* TFP errors (0x30 to 0x3F) */ -#define PXENV_STATUS_TFTP_CANNOT_ARP 0x30 /* TFTP ARP problem */ -#define PXENV_STATUS_TFTP_OPEN_CANCELED 0x31 /* TFTP open canceled by key */ -#define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x32 /* timeout during TFTP open */ -#define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x33 /* unknown TFTP opcode */ -#define PXENV_STATUS_TFTP_READ_CANCELED 0x34 /* TFTP read canceled by key */ -#define PXENV_STATUS_TFTP_READ_TIMEOUT 0x35 /* timeout during TFTP read */ -#define PXENV_STATUS_TFTP_ERROR_OPCODE 0x36 /* bad TFTP opcode */ -#define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION \ - 0x38 /* error during TFTP open */ -#define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION \ - 0x39 /* error during TFTP read */ -#define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES \ - 0x3A /* too many packages */ -#define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x3B /* file not found */ -#define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x3C /* access violation */ -#define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x3D /* no multicast address */ -#define PXENV_STATUS_TFTP_NO_FILESIZE 0x3E /* unable to get file size */ -#define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE \ - 0x3F /* invalid packet size */ - -/* BOOTP errors (0x40 to 0x4F) */ -#define PXENV_STATUS_BOOTP_CANCELED 0x40 /* BOOTP canceled by key */ -#define PXENV_STATUS_BOOTP_TIMEOUT 0x41 /* timeout during BOOTP */ -#define PXENV_STATUS_BOOTP_NO_FILE 0x42 /* missing bootfile name */ - -/* DHCP errors (0x50 to 0x5F) */ -#define PXENV_STATUS_DHCP_CANCELED 0x50 /* DHCP canceled by key */ -#define PXENV_STATUS_DHCP_TIMEOUT 0x51 /* timeout during DHCP */ -#define PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x52 /* missing IP address */ -#define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x53 /* missing bootfile name */ -#define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x54 /* invalid IP address */ - -/* Driver errors (0x60 to 0x6F) */ -#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x60 /* invalid UNDI function */ -#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x61 /* media test failed */ -#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST \ - 0x62 /* cannot init for multicast */ -#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC \ - 0x63 /* cannot init NIC */ -#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY \ - 0x64 /* cannot init hardware */ -#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA \ - 0x65 /* cannot read config data */ -#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA \ - 0x66 /* cannot read init data */ -#define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x67 /* invalid hardware address */ -#define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM \ - 0x68 /* invalid EEPROM checksum */ -#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x69 -#define PXENV_STATUS_UNDI_INVALID_STATE 0x6a /* invalid UNDI state */ -#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x6b /* transmit error */ -#define PXENV_STATUS_UNDI_INVALID_PARAMETER \ - 0x6c /* almost anything */ - -/* Bootstrap (.1) errors (0x70 to 0x7F) */ -#define PXENV_STATUS_BSTRAP_PROMPT_MENU 0x74 /* invalid bootstrap menu */ -#define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x76 /* missing multicast address */ -#define PXENV_STATUS_BSTRAP_MISSING_LIST 0x77 /* missing file list */ -#define PXENV_STATUS_BSTRAP_NO_RESPONSE 0x78 /* no response from server */ -#define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x79 /* next file too big */ - -/* Environment (.2) errors (0x80 to 0x8F) */ - -/* MTFTP errors (0x90 to 0x9F) */ -#define PXENV_STATUS_MTFTP_OPEN_CANCEL 0x91 /* MTFTP open canceled by key */ -#define PXENV_STATUS_MTFTP_OPEN_TIMEOUT 0x92 /* timeout during MTFTP open */ -#define PXENV_STATUS_MTFTP_UNKNOWN_OP 0x93 /* unknown TFTP opcode */ -#define PXENV_STATUS_MTFTP_READ_CANCEL 0x94 /* MTFTP read canceled by key */ -#define PXENV_STATUS_MTFTP_READ_TIMEOUT 0x95 /* timeout during MTFTP read */ -#define PXENV_STATUS_MTFTP_ERROR_OP 0x96 /* bad TFTP opcode */ -#define PXENV_STATUS_MTFTP_CANNOT_OPEN 0x98 /* error during MTFTP open */ -#define PXENV_STATUS_MTFTP_CANNOT_READ 0x99 /* error during MTFTP read */ -#define PXENV_STATUS_MTFTP_TOO_MANY 0x9A /* too many packages */ -#define PXENV_STATUS_MTFTP_PACK_SIZE 0x9B /* invalid package size */ - -/* Misc. errors (0xA0 to 0xAF) */ -#define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE \ - 0xA0 /* BINL canceled by key */ -#define PXENV_STATUS_BINL_NO_PXE_SERVER 0xA1 /* no BINL server found */ -#define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE \ - 0xA2 /* not avail. in prot mode */ -#define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE \ - 0xA3 /* not avail. in real mode */ - -/* BUSD errors (0xB0 to 0xBF) */ -#define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED \ - 0xB0 /* BUSD services not enabled */ -#define PXENV_STATUS_BUSD_DEV_ENABLE 0xB1 /* BUSD device not enabled */ - -/* Loader errors (0xC0 to 0xCF) */ -#define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY \ - 0xC0 /* no free base memory */ -#define PXENV_STATUS_LOADER_NO_BC_ROMID 0xC1 /* no base code rom ID */ -#define PXENV_STATUS_LOADER_BAD_BC_ROMID 0xC2 /* bad base code rom ID */ -#define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE \ - 0xC3 /* bad base code image */ -#define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0xC4 /* no UNDI rom ID */ -#define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0xC5 /* bad UNDI rom ID */ -#define PXENV_STATUS_LOADER_UNDI_DRIVER_IMAGE \ - 0xC6 /* bad UNDI runtime image */ -#define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0xC8 /* missing !PXE struct */ -#define PXENV_STATUS_LOADER_NO_PXENV_STRUCT \ - 0xC9 /* missing PXENV+ struct */ -#define PXENV_STATUS_LOADER_UNDI_START 0xCA /* UNDI not started */ -#define PXENV_STATUS_LOADER_BC_START 0xCB /* base code not started */ - -/* Reserved errors (0xD0 to 0xFF) */ -#define PXENV_STATUS_IMAGE_INVALID 0xD0 /* invalid boot image */ -#define PXENV_STATUS_STOP_BASE 0xD1 /* error stopping base code */ -#define PXENV_STATUS_UNLOAD_BASE 0xD2 /* error unloading base code */ -#define PXENV_STATUS_STOP_UNDI 0xD3 /* error stopping UNDI */ -#define PXENV_STATUS_CLEANUP_UNDI 0xD4 /* error cleaning up UNDI */ - - -/***************************************************************************** - * The remainder of this file is original to Etherboot. - ***************************************************************************** - */ - -/* Dummy PXE opcode for the loader routine. We do this to make the - * API simpler - */ -#define PXENV_UNDI_LOADER 0x104d /* 'load' */ - -typedef struct undi_loader { - union { - struct { - PXENV_STATUS_t Status; - uint16_t ax; - uint16_t bx; - uint16_t dx; - uint16_t di; - uint16_t es; - }; - t_PXENV_START_UNDI start_undi; - }; - uint16_t undi_ds; - uint16_t undi_cs; - SEGOFF16_t pxe_ptr; - SEGOFF16_t pxenv_ptr; -} PACKED undi_loader_t; +#include "pxe_types.h" +#include "pxe_api.h" +#include "etherboot.h" +#include "tftp.h" /* 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. */ -typedef union { - PXENV_STATUS_t Status; /* Make it easy to read status - for any operation */ - t_PXENV_START_UNDI start_undi; - t_PXENV_UNDI_STARTUP undi_startup; - t_PXENV_UNDI_CLEANUP undi_cleanup; - t_PXENV_UNDI_INITIALIZE undi_initialize; - t_PXENV_UNDI_RESET_ADAPTER undi_reset_adapter; - t_PXENV_UNDI_SHUTDOWN undi_shutdown; - t_PXENV_UNDI_OPEN undi_open; - t_PXENV_UNDI_CLOSE undi_close; - t_PXENV_UNDI_TRANSMIT undi_transmit; - t_PXENV_UNDI_SET_MCAST_ADDRESS undi_set_mcast_address; - t_PXENV_UNDI_SET_STATION_ADDRESS undi_set_station_address; - t_PXENV_UNDI_SET_PACKET_FILTER undi_set_packet_filter; - t_PXENV_UNDI_GET_INFORMATION undi_get_information; - t_PXENV_UNDI_GET_STATISTICS undi_get_statistics; - t_PXENV_UNDI_CLEAR_STATISTICS undi_clear_statistics; - t_PXENV_UNDI_INITIATE_DIAGS undi_initiate_diags; - t_PXENV_UNDI_FORCE_INTERRUPT undi_force_interrupt; - t_PXENV_UNDI_GET_MCAST_ADDRESS undi_get_mcast_address; - t_PXENV_UNDI_GET_NIC_TYPE undi_get_nic_type; - t_PXENV_UNDI_GET_IFACE_INFO undi_get_iface_info; - t_PXENV_UNDI_ISR undi_isr; - t_PXENV_STOP_UNDI stop_undi; - t_PXENV_TFTP_OPEN tftp_open; - t_PXENV_TFTP_CLOSE tftp_close; - t_PXENV_TFTP_READ tftp_read; - t_PXENV_TFTP_READ_FILE tftp_read_file; - t_PXENV_TFTP_GET_FSIZE tftp_get_fsize; - t_PXENV_UDP_OPEN udp_open; - t_PXENV_UDP_CLOSE udp_close; - t_PXENV_UDP_READ udp_read; - t_PXENV_UDP_WRITE udp_write; - t_PXENV_UNLOAD_STACK unload_stack; - t_PXENV_GET_CACHED_INFO get_cached_info; - t_PXENV_RESTART_TFTP restart_tftp; - t_PXENV_START_BASE start_base; - t_PXENV_STOP_BASE stop_base; - undi_loader_t loader; -} t_PXENV_ANY; +union u_PXENV_ANY { + /* Make it easy to read status for any operation */ + PXENV_STATUS_t Status; + 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; +}; + +typedef union u_PXENV_ANY PXENV_ANY_t; /* PXE stack status indicator. See pxe_export.c for further * explanation. @@ -900,22 +64,32 @@ typedef enum { READY } pxe_stack_state_t; +#define ENSURE_CAN_UNLOAD(structure) if ( ! ensure_pxe_state(CAN_UNLOAD) ) { \ + structure->Status = PXENV_STATUS_UNDI_INVALID_STATE; \ + return PXENV_EXIT_FAILURE; } +#define ENSURE_MIDWAY(structure) if ( ! ensure_pxe_state(MIDWAY) ) { \ + structure->Status = PXENV_STATUS_UNDI_INVALID_STATE; \ + return PXENV_EXIT_FAILURE; } +#define ENSURE_READY(structure) if ( ! ensure_pxe_state(READY) ) { \ + structure->Status = PXENV_STATUS_UNDI_INVALID_STATE; \ + return PXENV_EXIT_FAILURE; } + /* Data structures installed as part of a PXE stack. Architectures * will have extra information to append to the end of this. */ #define PXE_TFTP_MAGIC_COOKIE ( ( 'P'<<24 ) | ( 'x'<<16 ) | ( 'T'<<8 ) | 'f' ) -typedef struct { - pxe_t pxe __attribute__ ((aligned(16))); - pxenv_t pxenv __attribute__ ((aligned(16))); +typedef struct pxe_stack { + struct s_PXE pxe __attribute__ ((aligned(16))); + struct s_PXENV pxenv __attribute__ ((aligned(16))); pxe_stack_state_t state; union { - BOOTPLAYER cached_info; + BOOTPLAYER_t cached_info; char packet[ETH_FRAME_LEN]; struct { uint32_t magic_cookie; unsigned int len; int eof; - char data[TFTP_MAX_PACKET]; + char data[TFTP_MAX_BLKSIZE]; } tftpdata; struct { char *buffer; @@ -926,4 +100,10 @@ typedef struct { struct {} arch_data __attribute__ ((aligned(16))); } pxe_stack_t; +extern int ensure_pxe_state ( pxe_stack_state_t wanted ); + +extern pxe_stack_t *pxe_stack; + +extern PXENV_EXIT_t pxe_api_call ( int opcode, union u_PXENV_ANY *any ); + #endif /* PXE_H */ diff --git a/src/include/pxe_api.h b/src/include/pxe_api.h new file mode 100644 index 000000000..7256c57e5 --- /dev/null +++ b/src/include/pxe_api.h @@ -0,0 +1,1696 @@ +#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_loader_api PXE Loader API + * + * The UNDI ROM loader API + * + * @{ + */ + +/** The UNDI ROM ID structure */ +struct s_UNDI_ROM_ID { + /** Signature + * + * Contains the bytes 'U', 'N', 'D', 'I'. + */ + UINT32_t Signature; + 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; + /** UNDI revision + * + * UNDI revision, least significant byte first. For UNDI + * version 2.1.0, this field will contain { 0x00, 0x01, 0x02 }. + */ + UINT8_t UNDIRev[3]; + /** UNDI loader routine entry point + * + * This is the entry point for calling 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; + +typedef struct s_UNDI_ROM_ID UNDI_ROM_ID_t; + +/** Parameter block for undi_loader() */ +struct s_UNDI_LOADER { + /** struct s_UNDI_LOADER starts with a struct s_PXENV_START_UNDI */ + union undi_loader_start_undi { + PXENV_STATUS_t Status; /**< PXE status code */ + /** Parameters to pass to pxenv_start_undi() */ + struct s_PXENV_START_UNDI start_undi; + } u; + /** 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 pxe_ptr; + /** Address of the PXENV+ structure (a struct s_PXENV) */ + SEGOFF16_t pxenv_ptr; +} 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/src/include/pxe_export.h b/src/include/pxe_export.h deleted file mode 100644 index 3d39e73cf..000000000 --- a/src/include/pxe_export.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Header for pxe_export.c - */ - -#ifndef PXE_EXPORT_H -#define PXE_EXPORT_H - -#include "pxe.h" - -/* Function prototypes */ -extern int ensure_pxe_state ( pxe_stack_state_t wanted ); - -extern PXENV_EXIT_t pxenv_start_undi ( t_PXENV_START_UNDI * ); -extern PXENV_EXIT_t pxenv_undi_startup ( t_PXENV_UNDI_STARTUP * ); -extern PXENV_EXIT_t pxenv_undi_cleanup ( t_PXENV_UNDI_CLEANUP * ); -extern PXENV_EXIT_t pxenv_undi_initialize ( t_PXENV_UNDI_INITIALIZE * ); -extern PXENV_EXIT_t pxenv_undi_reset_adapter ( t_PXENV_UNDI_RESET_ADAPTER * ); -extern PXENV_EXIT_t pxenv_undi_shutdown ( t_PXENV_UNDI_SHUTDOWN * ); -extern PXENV_EXIT_t pxenv_undi_open ( t_PXENV_UNDI_OPEN * ); -extern PXENV_EXIT_t pxenv_undi_close ( t_PXENV_UNDI_CLOSE * ); -extern PXENV_EXIT_t pxenv_undi_transmit ( t_PXENV_UNDI_TRANSMIT * ); -extern PXENV_EXIT_t pxenv_undi_set_mcast_address ( - t_PXENV_UNDI_SET_MCAST_ADDRESS * ); -extern PXENV_EXIT_t pxenv_undi_set_station_address ( - t_PXENV_UNDI_SET_STATION_ADDRESS * ); -extern PXENV_EXIT_t pxenv_undi_set_packet_filter ( - t_PXENV_UNDI_SET_PACKET_FILTER * ); -extern PXENV_EXIT_t pxenv_undi_get_information ( - t_PXENV_UNDI_GET_INFORMATION * ); -extern PXENV_EXIT_t pxenv_undi_get_statistics ( t_PXENV_UNDI_GET_STATISTICS* ); -extern PXENV_EXIT_t pxenv_undi_clear_statistics ( - t_PXENV_UNDI_CLEAR_STATISTICS * ); -extern PXENV_EXIT_t pxenv_undi_initiate_diags ( t_PXENV_UNDI_INITIATE_DIAGS* ); -extern PXENV_EXIT_t pxenv_undi_force_interrupt ( - t_PXENV_UNDI_FORCE_INTERRUPT * ); -extern PXENV_EXIT_t pxenv_undi_get_mcast_address ( - t_PXENV_UNDI_GET_MCAST_ADDRESS * ); -extern PXENV_EXIT_t pxenv_undi_get_nic_type ( t_PXENV_UNDI_GET_NIC_TYPE * ); -extern PXENV_EXIT_t pxenv_undi_get_iface_info ( t_PXENV_UNDI_GET_IFACE_INFO *); -extern PXENV_EXIT_t pxenv_undi_isr ( t_PXENV_UNDI_ISR * ); -extern PXENV_EXIT_t pxenv_stop_undi ( t_PXENV_STOP_UNDI * ); -extern PXENV_EXIT_t pxenv_tftp_open ( t_PXENV_TFTP_OPEN * ); -extern PXENV_EXIT_t pxenv_tftp_close ( t_PXENV_TFTP_CLOSE * ); -extern PXENV_EXIT_t pxenv_tftp_read ( t_PXENV_TFTP_READ * ); -extern PXENV_EXIT_t pxenv_tftp_read_file ( t_PXENV_TFTP_READ_FILE * ); -extern PXENV_EXIT_t pxenv_tftp_get_fsize ( t_PXENV_TFTP_GET_FSIZE * ); -extern PXENV_EXIT_t pxenv_udp_open ( t_PXENV_UDP_OPEN * ); -extern PXENV_EXIT_t pxenv_udp_close ( t_PXENV_UDP_CLOSE * ); -extern PXENV_EXIT_t pxenv_udp_read ( t_PXENV_UDP_READ * ); -extern PXENV_EXIT_t pxenv_udp_write ( t_PXENV_UDP_WRITE * ); -extern PXENV_EXIT_t pxenv_unload_stack ( t_PXENV_UNLOAD_STACK * ); -extern PXENV_EXIT_t pxenv_get_cached_info ( t_PXENV_GET_CACHED_INFO * ); -extern PXENV_EXIT_t pxenv_restart_tftp ( t_PXENV_RESTART_TFTP * ); -extern PXENV_EXIT_t pxenv_start_base ( t_PXENV_START_BASE * ); -extern PXENV_EXIT_t pxenv_stop_base ( t_PXENV_STOP_BASE * ); - -extern PXENV_EXIT_t pxe_api_call ( int opcode, t_PXENV_ANY *params ); - -/* Static variables */ -extern pxe_stack_t *pxe_stack; - -#endif /* PXE_EXPORT_H */ diff --git a/src/include/pxe_types.h b/src/include/pxe_types.h new file mode 100644 index 000000000..80e6aa17c --- /dev/null +++ b/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/src/include/tables.h b/src/include/tables.h index 26ad61db7..c3e05e55e 100644 --- a/src/include/tables.h +++ b/src/include/tables.h @@ -1,47 +1,171 @@ #ifndef TABLES_H #define TABLES_H -/* - * Macros for dealing with linker-generated tables of fixed-size - * symbols. We make fairly extensive use of these in order to avoid - * ifdef spaghetti and/or linker symbol pollution. For example, - * instead of having code such as +/** @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 * - * #ifdef CONSOLE_SERIAL * serial_init(); - * #endif + * + * @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 ifdef - * spaghetti (having to conditionalise every reference to functions in - * serial.c). + * 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 ".tbl.NAME.NN" where - * NAME designates the data structure stored in the table - * (e.g. "init_fn") and NN is a two-digit decimal number used to - * impose an ordering upon the tables if required. NN=00 is reserved - * for the symbol indicating "table start", and NN=99 is reserved for - * the symbol indicating "table end". + * 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 * - * To define an entry in the "xxx" table: + * Any module providing frobnicating services would look something + * like * - * static struct xxx my_xxx __table(xxx,01) = { ... }; + * @code * - * To access start and end markers for the "xxx" table: + * #include "frob.h" * - * static struct xxx xxx_start[0] __table_start(xxx); - * static struct xxx xxx_end[0] __table_end(xxx); + * static void my_frob ( void ) { + * // Do my frobnicating + * ... + * } * - * See init.h and init.c for an example of how these macros are used - * in practice. + * static 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. * */ +#include "compiler.h" /* for doxygen */ + #define __table_str(x) #x #define __table_section(table,idx) \ __section__ ( ".tbl." __table_str(table) "." __table_str(idx) ) @@ -49,10 +173,54 @@ #define __table_section_start(table) __table_section(table,00) #define __table_section_end(table) __table_section(table,99) + +/** + * Linker table entry. + * + * Declares a data structure to be part of a linker table. Use as + * e.g. + * + * @code + * + * static struct my_foo __table ( foo, 01 ) = { + * ... + * }; + * + * @endcode + * + */ #define __table(table,idx) \ __attribute__ (( unused, __table_section(table,idx) )) + +/** + * 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(table) \ __attribute__ (( unused, __table_section_start(table) )) + +/** + * 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(table) \ __attribute__ (( unused, __table_section_end(table) )) diff --git a/src/include/tftp.h b/src/include/tftp.h index 70192067c..2a086eb2b 100644 --- a/src/include/tftp.h +++ b/src/include/tftp.h @@ -1,13 +1,17 @@ #ifndef TFTP_H #define TFTP_H +/** @file */ + #include "in.h" #include "buffer.h" #include "nic.h" +#include "ip.h" +#include "udp.h" -#define TFTP_PORT 69 -#define TFTP_DEFAULTSIZE_PACKET 512 -#define TFTP_MAX_PACKET 1432 /* 512 */ +#define TFTP_PORT 69 /**< Default TFTP server port */ +#define TFTP_DEFAULT_BLKSIZE 512 +#define TFTP_MAX_BLKSIZE 1432 /* 512 */ #define TFTP_RRQ 1 #define TFTP_WRQ 2 @@ -16,53 +20,131 @@ #define TFTP_ERROR 5 #define TFTP_OACK 6 -#define TFTP_CODE_EOF 1 -#define TFTP_CODE_MORE 2 -#define TFTP_CODE_ERROR 3 -#define TFTP_CODE_BOOT 4 -#define TFTP_CODE_CFG 5 +#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 */ + +/** A TFTP request (RRQ) packet */ +struct tftp_rrq { + struct iphdr ip; + struct udphdr udp; + uint16_t opcode; + char data[TFTP_DEFAULT_BLKSIZE]; +} PACKED; + +/** A TFTP data (DATA) packet */ +struct tftp_data { + struct iphdr ip; + struct udphdr udp; + uint16_t opcode; + uint16_t block; + uint8_t data[TFTP_MAX_BLKSIZE]; +} PACKED; + +/** A TFTP acknowledgement (ACK) packet */ +struct tftp_ack { + struct iphdr ip; + struct udphdr udp; + uint16_t opcode; + uint16_t block; +} PACKED; + +/** A TFTP error (ERROR) packet */ +struct tftp_error { + struct iphdr ip; + struct udphdr udp; + uint16_t opcode; + uint16_t errcode; + char errmsg[TFTP_DEFAULT_BLKSIZE]; +} PACKED; -struct tftp_t { +/** A TFTP options acknowledgement (OACK) packet */ +struct tftp_oack { struct iphdr ip; struct udphdr udp; uint16_t opcode; - union { - uint8_t rrq[TFTP_DEFAULTSIZE_PACKET]; - struct { - uint16_t block; - uint8_t download[TFTP_MAX_PACKET]; - } data; - struct { - uint16_t block; - } ack; - struct { - uint16_t errcode; - uint8_t errmsg[TFTP_DEFAULTSIZE_PACKET]; - } err; - struct { - uint8_t data[TFTP_DEFAULTSIZE_PACKET+2]; - } oack; - } u; + uint8_t data[TFTP_DEFAULT_BLKSIZE]; } PACKED; -/* define a smaller tftp packet solely for making requests to conserve stack - 512 bytes should be enough */ -struct tftpreq_t { +/** The common header of all TFTP packets */ +struct tftp_common { struct iphdr ip; struct udphdr udp; uint16_t opcode; - union { - uint8_t rrq[512]; - struct { - uint16_t block; - } ack; - struct { - uint16_t errcode; - uint8_t errmsg[512-2]; - } err; - } u; } 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; +}; + +/** + * TFTP state + * + * This data structure holds the state for an ongoing TFTP transfer. + */ +struct tftp_state { + /** TFTP server address + * + * This is the IP address and UDP port from which data packets + * will be sent, and to which ACK packets should be sent. + */ + struct sockaddr_in server; + /** TFTP client port + * + * This is the UDP port from which the open request will be + * sent, and to which any unicast data packets will be sent. + */ + in_port_t lport; + /** TFTP multicast address + * + * This is the IP address and UDP port to which multicast data + * packets, if any, will be sent. + */ + struct sockaddr_in multicast; + /** Master client + * + * This will be true if the client is the master client for a + * multicast protocol (i.e. MTFTP or TFTM). (It will always + * be true for a non-multicast protocol, i.e. plain old TFTP). + */ + int master; + /** Data block size + * + * This is the "blksize" option negotiated with the TFTP + * server. (If the TFTP server does not support TFTP options, + * this will default to 512). + */ + unsigned int blksize; + /** File size + * + * This is the value returned in the "tsize" option from the + * TFTP server. If the TFTP server does not support the + * "tsize" option, this value will be zero. + */ + off_t tsize; + /** Last received block + * + * The block number of the most recent block received from the + * TFTP server. Note that the first data block is block 1; a + * value of 0 indicates that no data blocks have yet been + * received. + */ + unsigned int block; +}; + + + struct tftpreq_info_t { struct sockaddr_in *server; const char *name; @@ -78,13 +160,4 @@ struct tftpblk_info_t { #define TFTP_MIN_PACKET (sizeof(struct iphdr) + sizeof(struct udphdr) + 4) -/* - * Functions in tftp.c. Needed for pxe_export.c - * - */ -extern int tftp_block ( struct tftpreq_info_t *request, - struct tftpblk_info_t *block ); -extern int tftp ( char *url, struct sockaddr_in *server, char *file, - struct buffer *buffer ); - #endif /* TFTP_H */ diff --git a/src/include/tftpcore.h b/src/include/tftpcore.h new file mode 100644 index 000000000..52f63bd9c --- /dev/null +++ b/src/include/tftpcore.h @@ -0,0 +1,33 @@ +#ifndef TFTPCORE_H +#define TFTPCORE_H + +/** @file + * + * TFTP core functions + * + * This file provides functions that are common to the TFTP (rfc1350), + * TFTM (rfc2090) and MTFTP (PXE) protocols. + * + */ + +#include "tftp.h" + +extern int tftp_open ( struct tftp_state *state, const char *filename, + union tftp_any **reply, int multicast ); + +extern int tftp_process_opts ( struct tftp_state *state, + struct tftp_oack *oack ); + +extern int tftp_ack_nowait ( struct tftp_state *state ); + +extern int tftp_get ( struct tftp_state *state, long timeout, + union tftp_any **reply ); + +extern int tftp_ack ( struct tftp_state *state, union tftp_any **reply ); + +extern int tftp_error ( struct tftp_state *state, int errcode, + const char *errmsg ); + +extern void tftp_set_errno ( struct tftp_error *error ); + +#endif /* TFTPCORE_H */ diff --git a/src/include/vsprintf.h b/src/include/vsprintf.h index 2bf200852..553ebeb55 100644 --- a/src/include/vsprintf.h +++ b/src/include/vsprintf.h @@ -1,10 +1,46 @@ #ifndef VSPRINTF_H #define VSPRINTF_H -/* - * Note that we cannot use __attribute__ (( format ( printf, ... ) )) - * to get automatic type checking on arguments, because we use - * non-standard format characters such as "%!" and "%@". +/** @file + * + * printf and friends. + * + * Etherboot's printf() functions understand the following format + * specifiers: + * + * - Hexadecimal integers + * - @c %[#]x - 4 bytes int (8 hex digits, lower case) + * - @c %[#]X - 4 bytes int (8 hex digits, upper case) + * - @c %[#]lx - 8 bytes long (16 hex digits, lower case) + * - @c %[#]lX - 8 bytes long (16 hex digits, upper case) + * - @c %[#]hx - 2 bytes int (4 hex digits, lower case) + * - @c %[#]hX - 2 bytes int (4 hex digits, upper case) + * - @c %[#]hhx - 1 byte int (2 hex digits, lower case) + * - @c %[#]hhX - 1 byte int (2 hex digits, upper case) + * . + * If the optional # prefix is specified, the output will + * be prefixed with 0x (or 0X). + * + * - Other integers + * - @c %d - decimal int + * . + * Note that any width specification (e.g. the @c 02 in @c %02x) + * will be accepted but ignored. + * + * - Strings and characters + * - @c %c - char + * - @c %s - string + * - @c %m - error message text (i.e. strerror(errno)) + * + * - Etherboot-specific specifiers + * - @c %@ - IP address in ddd.ddd.ddd.ddd notation + * - @c %! - MAC address in xx:xx:xx:xx:xx:xx notation + * + * + * @note Unfortunately, we cannot use <tt> __attribute__ (( format ( + * printf, ... ) )) </tt> to get automatic type checking on arguments, + * because we use non-standard format characters such as @c %! and + * @c %@. * */ |
