|  | /* | 
|  | *  GRUB  --  GRand Unified Bootloader | 
|  | *  Copyright (C) 2000,2001,2002  Free Software Foundation, Inc. | 
|  | * | 
|  | *  This program is free software; you can redistribute it and/or modify | 
|  | *  it under the terms of the GNU General Public License as published by | 
|  | *  the Free Software Foundation; either version 2 of the License, or | 
|  | *  (at your option) any later version. | 
|  | * | 
|  | *  This program is distributed in the hope that it will be useful, | 
|  | *  but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | *  GNU General Public License for more details. | 
|  | * | 
|  | *  You should have received a copy of the GNU General Public License | 
|  | *  along with this program; if not, write to the Free Software | 
|  | *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 
|  | */ | 
|  |  | 
|  | /* RULE: You must define the macro ``GRUB'' when including this header | 
|  | file in GRUB code.  */ | 
|  |  | 
|  | /* Based on "src/etherboot.h" in etherboot-5.0.5.  */ | 
|  |  | 
|  | /************************************************************************** | 
|  | ETHERBOOT -  BOOTP/TFTP Bootstrap Program | 
|  |  | 
|  | Author: Martin Renters | 
|  | Date: Dec/93 | 
|  |  | 
|  | **************************************************************************/ | 
|  |  | 
|  | /* Include GRUB-specific macros and prototypes here.  */ | 
|  | #include <shared.h> | 
|  |  | 
|  | /* FIXME: For now, enable the DHCP support. Perhaps I should segregate | 
|  | the DHCP support from the BOOTP support, and permit both to | 
|  | co-exist.  */ | 
|  | #undef NO_DHCP_SUPPORT | 
|  |  | 
|  | /* In GRUB, the relocated address in Etherboot doesn't have any sense. | 
|  | Just define it as a bogus value.  */ | 
|  | #define RELOC	0 | 
|  |  | 
|  | /* FIXME: Should be an option.  */ | 
|  | #define BACKOFF_LIMIT	7 | 
|  |  | 
|  | #include <osdep.h> | 
|  |  | 
|  | #define CTRL_C		3 | 
|  |  | 
|  | #ifndef	MAX_TFTP_RETRIES | 
|  | # define MAX_TFTP_RETRIES	20 | 
|  | #endif | 
|  |  | 
|  | #ifndef	MAX_BOOTP_RETRIES | 
|  | # define MAX_BOOTP_RETRIES	20 | 
|  | #endif | 
|  |  | 
|  | #define MAX_BOOTP_EXTLEN	(ETH_FRAME_LEN - ETH_HLEN - \ | 
|  | sizeof (struct bootp_t)) | 
|  |  | 
|  | #ifndef	MAX_ARP_RETRIES | 
|  | # define MAX_ARP_RETRIES	20 | 
|  | #endif | 
|  |  | 
|  | #ifndef	MAX_RPC_RETRIES | 
|  | # define MAX_RPC_RETRIES	20 | 
|  | #endif | 
|  |  | 
|  | #define	TICKS_PER_SEC		18 | 
|  |  | 
|  | /* Inter-packet retry in ticks */ | 
|  | #define TIMEOUT			(10 * TICKS_PER_SEC) | 
|  |  | 
|  | /* These settings have sense only if compiled with -DCONGESTED */ | 
|  | /* total retransmission timeout in ticks */ | 
|  | #define TFTP_TIMEOUT		(30 * TICKS_PER_SEC) | 
|  | /* packet retransmission timeout in ticks */ | 
|  | #define TFTP_REXMT		(3 * TICKS_PER_SEC) | 
|  |  | 
|  | #ifndef	NULL | 
|  | # define NULL			((void *) 0) | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | I'm moving towards the defined names in linux/if_ether.h for clarity. | 
|  | The confusion between 60/64 and 1514/1518 arose because the NS8390 | 
|  | counts the 4 byte frame checksum in the incoming packet, but not | 
|  | in the outgoing packet. 60/1514 are the correct numbers for most | 
|  | if not all of the other NIC controllers. I will be retiring the | 
|  | 64/1518 defines in the lead-up to 5.0. | 
|  | */ | 
|  |  | 
|  | #define ETH_ALEN		6	/* Size of Ethernet address */ | 
|  | #define ETH_HLEN		14	/* Size of ethernet header */ | 
|  | #define	ETH_ZLEN		60	/* Minimum packet */ | 
|  | /*#define ETH_MIN_PACKET		64*/ | 
|  | #define	ETH_FRAME_LEN		1514	/* Maximum packet */ | 
|  | /*#define ETH_MAX_PACKET		1518*/ | 
|  | /* Because some DHCP/BOOTP servers don't treat the maximum length the same | 
|  | as Etherboot, subtract the size of an IP header and that of an UDP | 
|  | header.  */ | 
|  | #define	ETH_MAX_MTU		(ETH_FRAME_LEN - ETH_HLEN \ | 
|  | - sizeof (struct iphdr) \ | 
|  | - sizeof (struct udphdr)) | 
|  |  | 
|  | #define ARP_CLIENT	0 | 
|  | #define ARP_SERVER	1 | 
|  | #define ARP_GATEWAY	2 | 
|  | #define ARP_ROOTSERVER	3 | 
|  | #define ARP_SWAPSERVER	4 | 
|  | #define MAX_ARP		ARP_SWAPSERVER+1 | 
|  |  | 
|  | #define	RARP_REQUEST	3 | 
|  | #define	RARP_REPLY	4 | 
|  |  | 
|  | #define IP		0x0800 | 
|  | #define ARP		0x0806 | 
|  | #define	RARP		0x8035 | 
|  |  | 
|  | #define BOOTP_SERVER	67 | 
|  | #define BOOTP_CLIENT	68 | 
|  | #define TFTP_PORT	69 | 
|  | #define SUNRPC_PORT	111 | 
|  |  | 
|  | #define IP_UDP		17 | 
|  | /* Same after going through htonl */ | 
|  | #define IP_BROADCAST	0xFFFFFFFF | 
|  |  | 
|  | #define ARP_REQUEST	1 | 
|  | #define ARP_REPLY	2 | 
|  |  | 
|  | #define BOOTP_REQUEST	1 | 
|  | #define BOOTP_REPLY	2 | 
|  |  | 
|  | #define TAG_LEN(p)		(*((p) + 1)) | 
|  | #define RFC1533_COOKIE		99, 130, 83, 99 | 
|  | #define RFC1533_PAD		0 | 
|  | #define RFC1533_NETMASK		1 | 
|  | #define RFC1533_TIMEOFFSET	2 | 
|  | #define RFC1533_GATEWAY		3 | 
|  | #define RFC1533_TIMESERVER	4 | 
|  | #define RFC1533_IEN116NS	5 | 
|  | #define RFC1533_DNS		6 | 
|  | #define RFC1533_LOGSERVER	7 | 
|  | #define RFC1533_COOKIESERVER	8 | 
|  | #define RFC1533_LPRSERVER	9 | 
|  | #define RFC1533_IMPRESSSERVER	10 | 
|  | #define RFC1533_RESOURCESERVER	11 | 
|  | #define RFC1533_HOSTNAME	12 | 
|  | #define RFC1533_BOOTFILESIZE	13 | 
|  | #define RFC1533_MERITDUMPFILE	14 | 
|  | #define RFC1533_DOMAINNAME	15 | 
|  | #define RFC1533_SWAPSERVER	16 | 
|  | #define RFC1533_ROOTPATH	17 | 
|  | #define RFC1533_EXTENSIONPATH	18 | 
|  | #define RFC1533_IPFORWARDING	19 | 
|  | #define RFC1533_IPSOURCEROUTING	20 | 
|  | #define RFC1533_IPPOLICYFILTER	21 | 
|  | #define RFC1533_IPMAXREASSEMBLY	22 | 
|  | #define RFC1533_IPTTL		23 | 
|  | #define RFC1533_IPMTU		24 | 
|  | #define RFC1533_IPMTUPLATEAU	25 | 
|  | #define RFC1533_INTMTU		26 | 
|  | #define RFC1533_INTLOCALSUBNETS	27 | 
|  | #define RFC1533_INTBROADCAST	28 | 
|  | #define RFC1533_INTICMPDISCOVER	29 | 
|  | #define RFC1533_INTICMPRESPOND	30 | 
|  | #define RFC1533_INTROUTEDISCOVER 31 | 
|  | #define RFC1533_INTROUTESOLICIT	32 | 
|  | #define RFC1533_INTSTATICROUTES	33 | 
|  | #define RFC1533_LLTRAILERENCAP	34 | 
|  | #define RFC1533_LLARPCACHETMO	35 | 
|  | #define RFC1533_LLETHERNETENCAP	36 | 
|  | #define RFC1533_TCPTTL		37 | 
|  | #define RFC1533_TCPKEEPALIVETMO	38 | 
|  | #define RFC1533_TCPKEEPALIVEGB	39 | 
|  | #define RFC1533_NISDOMAIN	40 | 
|  | #define RFC1533_NISSERVER	41 | 
|  | #define RFC1533_NTPSERVER	42 | 
|  | #define RFC1533_VENDOR		43 | 
|  | #define RFC1533_NBNS		44 | 
|  | #define RFC1533_NBDD		45 | 
|  | #define RFC1533_NBNT		46 | 
|  | #define RFC1533_NBSCOPE		47 | 
|  | #define RFC1533_XFS		48 | 
|  | #define RFC1533_XDM		49 | 
|  | #ifndef	NO_DHCP_SUPPORT | 
|  | #define RFC2132_REQ_ADDR	50 | 
|  | #define RFC2132_MSG_TYPE	53 | 
|  | #define RFC2132_SRV_ID		54 | 
|  | #define RFC2132_PARAM_LIST	55 | 
|  | #define RFC2132_MAX_SIZE	57 | 
|  | #define RFC2132_VENDOR_CLASS_ID	60 | 
|  |  | 
|  | #define DHCPDISCOVER		1 | 
|  | #define DHCPOFFER		2 | 
|  | #define DHCPREQUEST		3 | 
|  | #define DHCPACK			5 | 
|  | #endif	/* NO_DHCP_SUPPORT */ | 
|  |  | 
|  | #define RFC1533_VENDOR_MAJOR	0 | 
|  | #define RFC1533_VENDOR_MINOR	0 | 
|  |  | 
|  | #define RFC1533_VENDOR_MAGIC	128 | 
|  | #define RFC1533_VENDOR_ADDPARM	129 | 
|  | #define RFC1533_VENDOR_MNUOPTS	160 | 
|  | #define RFC1533_VENDOR_SELECTION 176 | 
|  | #define RFC1533_VENDOR_MOTD	184 | 
|  | #define RFC1533_VENDOR_NUMOFMOTD 8 | 
|  | #define RFC1533_VENDOR_IMG	192 | 
|  | #define RFC1533_VENDOR_NUMOFIMG	16 | 
|  |  | 
|  | #define RFC1533_VENDOR_CONFIGFILE	150 | 
|  |  | 
|  | #define RFC1533_END		255 | 
|  |  | 
|  | #define BOOTP_VENDOR_LEN	64 | 
|  | #ifndef	NO_DHCP_SUPPORT | 
|  | #define DHCP_OPT_LEN		312 | 
|  | #endif	/* NO_DHCP_SUPPORT */ | 
|  |  | 
|  | #define	TFTP_DEFAULTSIZE_PACKET	512 | 
|  | #define	TFTP_MAX_PACKET		1432 /* 512 */ | 
|  |  | 
|  | #define TFTP_RRQ	1 | 
|  | #define TFTP_WRQ	2 | 
|  | #define TFTP_DATA	3 | 
|  | #define TFTP_ACK	4 | 
|  | #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 AWAIT_ARP	0 | 
|  | #define AWAIT_BOOTP	1 | 
|  | #define AWAIT_TFTP	2 | 
|  | #define AWAIT_RARP	3 | 
|  | #define AWAIT_RPC	4 | 
|  | #define AWAIT_QDRAIN	5	/* drain queue, process ARP requests */ | 
|  |  | 
|  | typedef struct | 
|  | { | 
|  | unsigned long	s_addr; | 
|  | } | 
|  | in_addr; | 
|  |  | 
|  | struct arptable_t | 
|  | { | 
|  | in_addr ipaddr; | 
|  | unsigned char node[6]; | 
|  | }; | 
|  |  | 
|  | /* | 
|  | * A pity sipaddr and tipaddr are not longword aligned or we could use | 
|  | * in_addr. No, I don't want to use #pragma packed. | 
|  | */ | 
|  | struct arprequest | 
|  | { | 
|  | unsigned short hwtype; | 
|  | unsigned short protocol; | 
|  | char hwlen; | 
|  | char protolen; | 
|  | unsigned short opcode; | 
|  | char shwaddr[6]; | 
|  | char sipaddr[4]; | 
|  | char thwaddr[6]; | 
|  | char tipaddr[4]; | 
|  | }; | 
|  |  | 
|  | struct iphdr | 
|  | { | 
|  | char verhdrlen; | 
|  | char service; | 
|  | unsigned short len; | 
|  | unsigned short ident; | 
|  | unsigned short frags; | 
|  | char ttl; | 
|  | char protocol; | 
|  | unsigned short chksum; | 
|  | in_addr src; | 
|  | in_addr dest; | 
|  | }; | 
|  |  | 
|  | struct udphdr | 
|  | { | 
|  | unsigned short src; | 
|  | unsigned short dest; | 
|  | unsigned short len; | 
|  | unsigned short chksum; | 
|  | }; | 
|  |  | 
|  | /* Format of a bootp packet.  */ | 
|  | struct bootp_t | 
|  | { | 
|  | char bp_op; | 
|  | char bp_htype; | 
|  | char bp_hlen; | 
|  | char bp_hops; | 
|  | unsigned long bp_xid; | 
|  | unsigned short bp_secs; | 
|  | unsigned short unused; | 
|  | in_addr bp_ciaddr; | 
|  | in_addr bp_yiaddr; | 
|  | in_addr bp_siaddr; | 
|  | in_addr bp_giaddr; | 
|  | char bp_hwaddr[16]; | 
|  | char bp_sname[64]; | 
|  | char bp_file[128]; | 
|  | #ifdef	NO_DHCP_SUPPORT | 
|  | char bp_vend[BOOTP_VENDOR_LEN]; | 
|  | #else | 
|  | char bp_vend[DHCP_OPT_LEN]; | 
|  | #endif	/* NO_DHCP_SUPPORT */ | 
|  | }; | 
|  |  | 
|  | /* Format of a bootp IP packet.  */ | 
|  | struct bootpip_t | 
|  | { | 
|  | struct iphdr ip; | 
|  | struct udphdr udp; | 
|  | struct bootp_t bp; | 
|  | }; | 
|  |  | 
|  | /* Format of bootp packet with extensions.  */ | 
|  | struct bootpd_t | 
|  | { | 
|  | struct bootp_t bootp_reply; | 
|  | unsigned char  bootp_extension[MAX_BOOTP_EXTLEN]; | 
|  | }; | 
|  |  | 
|  | struct tftp_t | 
|  | { | 
|  | struct iphdr ip; | 
|  | struct udphdr udp; | 
|  | unsigned short opcode; | 
|  | union | 
|  | { | 
|  | char rrq[TFTP_DEFAULTSIZE_PACKET]; | 
|  |  | 
|  | struct | 
|  | { | 
|  | unsigned short block; | 
|  | char download[TFTP_MAX_PACKET]; | 
|  | } | 
|  | data; | 
|  |  | 
|  | struct | 
|  | { | 
|  | unsigned short block; | 
|  | } | 
|  | ack; | 
|  |  | 
|  | struct | 
|  | { | 
|  | unsigned short errcode; | 
|  | char errmsg[TFTP_DEFAULTSIZE_PACKET]; | 
|  | } | 
|  | err; | 
|  |  | 
|  | struct | 
|  | { | 
|  | char data[TFTP_DEFAULTSIZE_PACKET+2]; | 
|  | } | 
|  | oack; | 
|  | } | 
|  | u; | 
|  | }; | 
|  |  | 
|  | /* Define a smaller tftp packet solely for making requests to conserve stack | 
|  | 512 bytes should be enough.  */ | 
|  | struct tftpreq_t | 
|  | { | 
|  | struct iphdr ip; | 
|  | struct udphdr udp; | 
|  | unsigned short opcode; | 
|  | union | 
|  | { | 
|  | char rrq[512]; | 
|  |  | 
|  | struct | 
|  | { | 
|  | unsigned short block; | 
|  | } | 
|  | ack; | 
|  |  | 
|  | struct | 
|  | { | 
|  | unsigned short errcode; | 
|  | char errmsg[512-2]; | 
|  | } | 
|  | err; | 
|  | } | 
|  | u; | 
|  | }; | 
|  |  | 
|  | #define TFTP_MIN_PACKET	(sizeof(struct iphdr) + sizeof(struct udphdr) + 4) | 
|  |  | 
|  | struct rpc_t | 
|  | { | 
|  | struct iphdr ip; | 
|  | struct udphdr udp; | 
|  | union | 
|  | { | 
|  | char data[300];		/* longest RPC call must fit!!!! */ | 
|  |  | 
|  | struct | 
|  | { | 
|  | long id; | 
|  | long type; | 
|  | long rpcvers; | 
|  | long prog; | 
|  | long vers; | 
|  | long proc; | 
|  | long data[1]; | 
|  | } | 
|  | call; | 
|  |  | 
|  | struct | 
|  | { | 
|  | long id; | 
|  | long type; | 
|  | long rstatus; | 
|  | long verifier; | 
|  | long v2; | 
|  | long astatus; | 
|  | long data[1]; | 
|  | } | 
|  | reply; | 
|  | } | 
|  | u; | 
|  | }; | 
|  |  | 
|  | #define PROG_PORTMAP	100000 | 
|  | #define PROG_NFS	100003 | 
|  | #define PROG_MOUNT	100005 | 
|  |  | 
|  | #define MSG_CALL	0 | 
|  | #define MSG_REPLY	1 | 
|  |  | 
|  | #define PORTMAP_GETPORT	3 | 
|  |  | 
|  | #define MOUNT_ADDENTRY	1 | 
|  | #define MOUNT_UMOUNTALL	4 | 
|  |  | 
|  | #define NFS_LOOKUP	4 | 
|  | #define NFS_READ	6 | 
|  |  | 
|  | #define NFS_FHSIZE	32 | 
|  |  | 
|  | #define NFSERR_PERM	1 | 
|  | #define NFSERR_NOENT	2 | 
|  | #define NFSERR_ACCES	13 | 
|  |  | 
|  | /* Block size used for NFS read accesses.  A RPC reply packet (including  all | 
|  | * headers) must fit within a single Ethernet frame to avoid fragmentation. | 
|  | * Chosen to be a power of two, as most NFS servers are optimized for this.  */ | 
|  | #define NFS_READ_SIZE	1024 | 
|  |  | 
|  | #define	FLOPPY_BOOT_LOCATION	0x7c00 | 
|  | /* Must match offsets in loader.S */ | 
|  | #define ROM_SEGMENT		0x1fa | 
|  | #define ROM_LENGTH		0x1fc | 
|  |  | 
|  | #define	ROM_INFO_LOCATION	(FLOPPY_BOOT_LOCATION + ROM_SEGMENT) | 
|  | /* at end of floppy boot block */ | 
|  |  | 
|  | struct rom_info | 
|  | { | 
|  | unsigned short	rom_segment; | 
|  | unsigned short	rom_length; | 
|  | }; | 
|  |  | 
|  | static inline int | 
|  | rom_address_ok (struct rom_info *rom, int assigned_rom_segment) | 
|  | { | 
|  | return (assigned_rom_segment < 0xC000 | 
|  | || assigned_rom_segment == rom->rom_segment); | 
|  | } | 
|  |  | 
|  | /* Define a type for passing info to a loaded program.  */ | 
|  | struct ebinfo | 
|  | { | 
|  | unsigned char	major, minor;	/* Version */ | 
|  | unsigned short	flags;		/* Bit flags */ | 
|  | }; | 
|  |  | 
|  | /*************************************************************************** | 
|  | External prototypes | 
|  | ***************************************************************************/ | 
|  | /* main.c */ | 
|  | extern void print_network_configuration (void); | 
|  | extern int ifconfig (char *ip, char *sm, char *gw, char *svr); | 
|  | extern int udp_transmit (unsigned long destip, unsigned int srcsock, | 
|  | unsigned int destsock, int len, const void *buf); | 
|  | extern int await_reply (int type, int ival, void *ptr, int timeout); | 
|  | extern int decode_rfc1533 (unsigned char *, int, int, int); | 
|  | extern long rfc2131_sleep_interval (int base, int exp); | 
|  | extern void cleanup (void); | 
|  | extern int rarp (void); | 
|  | extern int bootp (void); | 
|  | extern void cleanup_net (void); | 
|  |  | 
|  | /* config.c */ | 
|  | extern void print_config (void); | 
|  | extern void eth_reset (void); | 
|  | extern int eth_probe (void); | 
|  | extern int eth_poll (void); | 
|  | extern void eth_transmit (const char *d, unsigned int t, | 
|  | unsigned int s, const void *p); | 
|  | extern void eth_disable (void); | 
|  |  | 
|  | /* misc.c */ | 
|  | extern void twiddle (void); | 
|  | extern void sleep (int secs); | 
|  | extern int getdec (char **s); | 
|  | extern void etherboot_printf (const char *, ...); | 
|  | extern int etherboot_sprintf (char *, const char *, ...); | 
|  | extern int inet_aton (char *p, in_addr *i); | 
|  |  | 
|  | /*************************************************************************** | 
|  | External variables | 
|  | ***************************************************************************/ | 
|  | /* main.c */ | 
|  | extern int ip_abort; | 
|  | extern int network_ready; | 
|  | extern struct rom_info rom; | 
|  | extern struct arptable_t arptable[MAX_ARP]; | 
|  | extern struct bootpd_t bootp_data; | 
|  | #define	BOOTP_DATA_ADDR	(&bootp_data) | 
|  | extern unsigned char *end_of_rfc1533; | 
|  |  | 
|  | /* config.c */ | 
|  | extern struct nic nic; | 
|  |  | 
|  | /* Local hack - define some macros to use etherboot source files "as is".  */ | 
|  | #ifndef GRUB | 
|  | # undef printf | 
|  | # define printf	etherboot_printf | 
|  | # undef sprintf | 
|  | # define sprintf etherboot_sprintf | 
|  | #endif /* GRUB */ |