1/*
2 * Copyright (c) 2000 Alfred Perlstein <alfred@freebsd.org>
3 * All rights reserved.
4 * Copyright (c) 2000 Paul Saab <ps@freebsd.org>
5 * All rights reserved.
6 * Copyright (c) 2000 John Baldwin <jhb@freebsd.org>
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * $FreeBSD$
31 */
32
33/*
34 * The typedefs and structures declared in this file
35 * clearly violate style(9), the reason for this is to conform to the
36 * typedefs/structure-names used in the Intel literature to avoid confusion.
37 *
38 * It's for your own good. :)
39 */
40
41/* It seems that intel didn't think about ABI,
42 * either that or 16bit ABI != 32bit ABI (which seems reasonable)
43 * I have to thank Intel for the hair loss I incurred trying to figure
44 * out why PXE was mis-reading structures I was passing it (at least
45 * from my point of view)
46 *
47 * Solution: use gcc's '__packed' to correctly align
48 * structures passed into PXE
49 * Question: does this really work for PXE's expected ABI?
50 */
51#define	PACKED		__packed
52
53#define	S_SIZE(s)	s, sizeof(s) - 1
54
55#define	IP_STR		"%d.%d.%d.%d"
56#define	IP_ARGS(ip)					\
57	(int)(ip >> 24) & 0xff, (int)(ip >> 16) & 0xff, \
58	(int)(ip >> 8) & 0xff, (int)ip & 0xff
59
60#define	MAC_STR		"%02x:%02x:%02x:%02x:%02x:%02x"
61#define	MAC_ARGS(mac)					\
62	mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]
63
64#define	PXENFSROOTPATH	"/pxeroot"
65
66typedef struct {
67	uint16_t		offset;
68	uint16_t		segment;
69} SEGOFF16_t;
70
71typedef struct {
72	uint16_t		Seg_Addr;
73	uint32_t		Phy_Addr;
74	uint16_t		Seg_Size;
75} SEGDESC_t;
76
77typedef	uint16_t		SEGSEL_t;
78typedef	uint16_t		PXENV_STATUS_t;
79typedef	uint32_t		IP4_t;
80typedef	uint32_t		ADDR32_t;
81typedef	uint16_t		UDP_PORT_t;
82
83#define	MAC_ADDR_LEN		16
84typedef	uint8_t			MAC_ADDR[MAC_ADDR_LEN];
85
86/* PXENV+ */
87typedef struct {
88	uint8_t		Signature[6];	/* 'PXENV+' */
89	uint16_t	Version;	/* MSB = major, LSB = minor */
90	uint8_t		Length;		/* structure length */
91	uint8_t		Checksum;	/* checksum pad */
92	SEGOFF16_t	RMEntry;	/* SEG:OFF to PXE entry point */
93	/* don't use PMOffset and PMSelector (from the 2.1 PXE manual) */
94	uint32_t	PMOffset;	/* Protected mode entry */
95	SEGSEL_t	PMSelector;	/* Protected mode selector */
96	SEGSEL_t	StackSeg;	/* Stack segment address */
97	uint16_t	StackSize;	/* Stack segment size (bytes) */
98	SEGSEL_t	BC_CodeSeg;	/* BC Code segment address */
99	uint16_t	BC_CodeSize;	/* BC Code segment size (bytes) */
100	SEGSEL_t	BC_DataSeg;	/* BC Data segment address */
101	uint16_t	BC_DataSize;	/* BC Data segment size (bytes) */
102	SEGSEL_t	UNDIDataSeg;	/* UNDI Data segment address */
103	uint16_t	UNDIDataSize;	/* UNDI Data segment size (bytes) */
104	SEGSEL_t	UNDICodeSeg;	/* UNDI Code segment address */
105	uint16_t	UNDICodeSize;	/* UNDI Code segment size (bytes) */
106	SEGOFF16_t	PXEPtr;		/* SEG:OFF to !PXE struct,
107					   only present when Version > 2.1 */
108} PACKED pxenv_t;
109
110/* !PXE */
111typedef struct {
112	uint8_t		Signature[4];
113	uint8_t		StructLength;
114	uint8_t		StructCksum;
115	uint8_t		StructRev;
116	uint8_t		reserved_1;
117	SEGOFF16_t	UNDIROMID;
118	SEGOFF16_t	BaseROMID;
119	SEGOFF16_t	EntryPointSP;
120	SEGOFF16_t	EntryPointESP;
121	SEGOFF16_t	StatusCallout;
122	uint8_t		reserved_2;
123	uint8_t		SegDescCn;
124	SEGSEL_t	FirstSelector;
125	SEGDESC_t	Stack;
126	SEGDESC_t	UNDIData;
127	SEGDESC_t	UNDICode;
128	SEGDESC_t	UNDICodeWrite;
129	SEGDESC_t	BC_Data;
130	SEGDESC_t	BC_Code;
131	SEGDESC_t	BC_CodeWrite;
132} PACKED pxe_t;
133
134#define	PXENV_START_UNDI		0x0000
135typedef struct {
136	PXENV_STATUS_t	Status;
137	uint16_t	ax;
138	uint16_t	bx;
139	uint16_t	dx;
140	uint16_t	di;
141	uint16_t	es;
142} PACKED t_PXENV_START_UNDI;
143
144#define	PXENV_UNDI_STARTUP		0x0001
145typedef struct {
146	PXENV_STATUS_t	Status;
147} PACKED t_PXENV_UNDI_STARTUP;
148
149#define	PXENV_UNDI_CLEANUP		0x0002
150typedef struct {
151	PXENV_STATUS_t	Status;
152} PACKED t_PXENV_UNDI_CLEANUP;
153
154#define	PXENV_UNDI_INITIALIZE		0x0003
155typedef struct {
156	PXENV_STATUS_t	Status;
157	ADDR32_t	ProtocolIni;	/* Phys addr of a copy of the driver module */
158	uint8_t		reserved[8];
159} PACKED t_PXENV_UNDI_INITALIZE;
160
161
162#define	MAXNUM_MCADDR		8
163typedef struct {
164	PXENV_STATUS_t	Status;
165	uint16_t	MCastAddrCount;
166	MAC_ADDR	McastAddr[MAXNUM_MCADDR];
167} PACKED t_PXENV_UNDI_MCAST_ADDRESS;
168
169#define	PXENV_UNDI_RESET_ADAPTER	0x0004
170typedef struct {
171	PXENV_STATUS_t	Status;
172	t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
173} PACKED t_PXENV_UNDI_RESET;
174
175#define	PXENV_UNDI_SHUTDOWN		0x0005
176typedef struct {
177	PXENV_STATUS_t	Status;
178} PACKED t_PXENV_UNDI_SHUTDOWN;
179
180#define	PXENV_UNDI_OPEN			0x0006
181typedef struct {
182	PXENV_STATUS_t	Status;
183	uint16_t	OpenFlag;
184	uint16_t	PktFilter;
185#	define FLTR_DIRECTED	0x0001
186#	define FLTR_BRDCST	0x0002
187#	define FLTR_PRMSCS	0x0003
188#	define FLTR_SRC_RTG	0x0004
189
190	t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
191} PACKED t_PXENV_UNDI_OPEN;
192
193#define	PXENV_UNDI_CLOSE		0x0007
194typedef struct {
195	PXENV_STATUS_t	Status;
196} PACKED t_PXENV_UNDI_CLOSE;
197
198#define	PXENV_UNDI_TRANSMIT		0x0008
199typedef struct {
200	PXENV_STATUS_t	Status;
201	uint8_t		Protocol;
202#	define P_UNKNOWN	0
203#	define P_IP		1
204#	define P_ARP		2
205#	define P_RARP		3
206
207	uint8_t		XmitFlag;
208#	define XMT_DESTADDR	0x0000
209#	define XMT_BROADCAST	0x0001
210
211	SEGOFF16_t	DestAddr;
212	SEGOFF16_t	TBD;
213	uint32_t	Reserved[2];
214} PACKED t_PXENV_UNDI_TRANSMIT;
215
216#define	MAX_DATA_BLKS		8
217typedef struct {
218	uint16_t	ImmedLength;
219	SEGOFF16_t	Xmit;
220	uint16_t	DataBlkCount;
221	struct	DataBlk {
222		uint8_t		TDPtrType;
223		uint8_t		TDRsvdByte;
224		uint16_t	TDDataLen;
225		SEGOFF16_t	TDDataPtr;
226	} DataBlock[MAX_DATA_BLKS];
227} PACKED t_PXENV_UNDI_TBD;
228
229#define	PXENV_UNDI_SET_MCAST_ADDRESS	0x0009
230typedef struct {
231	PXENV_STATUS_t	Status;
232	t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf;
233} PACKED t_PXENV_UNDI_SET_MCAST_ADDR;
234
235#define	PXENV_UNDI_SET_STATION_ADDRESS	0x000A
236typedef struct {
237	PXENV_STATUS_t	Status;
238	MAC_ADDR	StationAddress;		/* Temp MAC addres to use */
239} PACKED t_PXENV_UNDI_SET_STATION_ADDR;
240
241#define	PXENV_UNDI_SET_PACKET_FILTER	0x000B
242typedef struct {
243	PXENV_STATUS_t	Status;
244	uint8_t		filter;			/* see UNDI_OPEN (0x0006) */
245} PACKED t_PXENV_UNDI_SET_PACKET_FILTER;
246
247#define	PXENV_UNDI_GET_INFORMATION	0x000C
248typedef struct {
249	PXENV_STATUS_t	Status;
250	uint16_t	BaseIo;			/* Adapter base I/O address */
251	uint16_t	IntNumber;		/* Adapter IRQ number */
252	uint16_t	MaxTranUnit;		/* Adapter maximum transmit unit */
253	uint16_t	HwType;			/* Type of protocol at the hardware addr */
254#	define ETHER_TYPE	1
255#	define EXP_ETHER_TYPE	2
256#	define IEEE_TYPE	6
257#	define ARCNET_TYPE	7
258
259	uint16_t	HwAddrLen;		/* Length of hardware address */
260	MAC_ADDR	CurrentNodeAddress;	/* Current hardware address */
261	MAC_ADDR	PermNodeAddress;	/* Permanent hardware address */
262	SEGSEL_t	ROMAddress;		/* Real mode ROM segment address */
263	uint16_t	RxBufCt;		/* Receive queue length */
264	uint16_t	TxBufCt;		/* Transmit queue length */
265} PACKED t_PXENV_UNDI_GET_INFORMATION;
266
267#define	PXENV_UNDI_GET_STATISTICS	0x000D
268typedef struct {
269	PXENV_STATUS_t	Status;
270	uint32_t	XmitGoodFrames;		/* Number of successful transmissions */
271	uint32_t	RcvGoodFrames;		/* Number of good frames received */
272	uint32_t	RcvCRCErrors;		/* Number of frames with CRC errors */
273	uint32_t	RcvResourceErrors;	/* Number of frames dropped */
274} PACKED t_PXENV_UNDI_GET_STATISTICS;
275
276#define	PXENV_UNDI_CLEAR_STATISTICS	0x000E
277typedef struct {
278	PXENV_STATUS_t	Status;
279} PACKED t_PXENV_UNDI_CLEAR_STATISTICS;
280
281#define	PXENV_UNDI_INITIATE_DIAGS	0x000F
282typedef struct {
283	PXENV_STATUS_t	Status;
284} PACKED t_PXENV_UNDI_INITIATE_DIAGS;
285
286#define	PXENV_UNDI_FORCE_INTERRUPT	0x0010
287typedef struct {
288	PXENV_STATUS_t	Status;
289} PACKED t_PXENV_UNDI_FORCE_INTERRUPT;
290
291#define	PXENV_UNDI_GET_MCAST_ADDRESS	0x0011
292typedef struct {
293	PXENV_STATUS_t	Status;
294	IP4_t		InetAddr;		/* IP mulicast address */
295	MAC_ADDR	MediaAddr;		/* MAC multicast address */
296} PACKED t_PXENV_UNDI_GET_MCAST_ADDR;
297
298#define	PXENV_UNDI_GET_NIC_TYPE		0x0012
299typedef struct {
300	PXENV_STATUS_t	Status;
301	uint8_t		NicType;		/* Type of NIC */
302#	define PCI_NIC		2
303#	define PnP_NIC		3
304#	define CardBus_NIC	4
305
306	union {
307		struct {
308			uint16_t	Vendor_ID;
309			uint16_t	Dev_ID;
310			uint8_t		Base_Class;
311			uint8_t		Sub_Class;
312			uint8_t		Prog_Intf;
313			uint8_t		Rev;
314			uint16_t	BusDevFunc;
315			uint16_t	SubVendor_ID;
316			uint16_t	SubDevice_ID;
317		} pci, cardbus;
318		struct {
319			uint32_t	EISA_Dev_ID;
320			uint8_t		Base_Class;
321			uint8_t		Sub_Class;
322			uint8_t		Prog_Intf;
323			uint16_t	CardSelNum;
324		} pnp;
325	} info;
326} PACKED t_PXENV_UNDI_GET_NIC_TYPE;
327
328#define	PXENV_UNDI_GET_IFACE_INFO	0x0013
329typedef struct {
330	PXENV_STATUS_t	Status;
331	uint8_t		IfaceType[16];		/* Name of MAC type in ASCII. */
332	uint32_t	LinkSpeed;		/* Defined in NDIS 2.0 spec */
333	uint32_t	ServiceFlags;		/* Defined in NDIS 2.0 spec */
334	uint32_t	Reserved[4];		/* must be 0 */
335} PACKED t_PXENV_UNDI_GET_NDIS_INFO;
336
337#define	PXENV_UNDI_ISR			0x0014
338typedef struct {
339	PXENV_STATUS_t	Status;
340	uint16_t	FuncFlag;		/* PXENV_UNDI_ISR_OUT_xxx */
341	uint16_t	BufferLength;		/* Length of Frame */
342	uint16_t	FrameLength;		/* Total length of reciever frame */
343	uint16_t	FrameHeaderLength;	/* Length of the media header in Frame */
344	SEGOFF16_t	Frame;			/* receive buffer */
345	uint8_t		ProtType;		/* Protocol type */
346	uint8_t		PktType;		/* Packet Type */
347#	define PXENV_UNDI_ISR_IN_START		1
348#	define PXENV_UNDI_ISR_IN_PROCESS	2
349#	define PXENV_UNDI_ISR_IN_GET_NEXT	3
350
351	/* one of these will be returned for PXENV_UNDI_ISR_IN_START */
352#	define PXENV_UNDI_ISR_OUT_OURS		0
353#	define PXENV_UNDI_ISR_OUT_NOT_OUTS	1
354
355	/*
356	 * one of these will bre returnd for PXEND_UNDI_ISR_IN_PROCESS
357	 * and PXENV_UNDI_ISR_IN_GET_NEXT
358	 */
359#	define PXENV_UNDI_ISR_OUT_DONE		0
360#	define PXENV_UNDI_ISR_OUT_TRANSMIT	2
361#	define PXENV_UNDI_ISR_OUT_RECIEVE	3
362#	define PXENV_UNDI_ISR_OUT_BUSY		4
363} PACKED t_PXENV_UNDI_ISR;
364
365#define	PXENV_STOP_UNDI			0x0015
366typedef struct {
367	PXENV_STATUS_t	Status;
368} PACKED t_PXENV_STOP_UNDI;
369
370#define	PXENV_TFTP_OPEN			0x0020
371typedef struct {
372	PXENV_STATUS_t	Status;
373	IP4_t		ServerIPAddress;
374	IP4_t		GatewayIPAddress;
375	uint8_t		FileName[128];
376	UDP_PORT_t	TFTPPort;
377	uint16_t	PacketSize;
378} PACKED t_PXENV_TFTP_OPEN;
379
380#define	PXENV_TFTP_CLOSE		0x0021
381typedef struct {
382	PXENV_STATUS_t	Status;
383} PACKED t_PXENV_TFTP_CLOSE;
384
385#define	PXENV_TFTP_READ			0x0022
386typedef struct {
387	PXENV_STATUS_t	Status;
388	uint16_t	PacketNumber;
389	uint16_t	BufferSize;
390	SEGOFF16_t	Buffer;
391} PACKED t_PXENV_TFTP_READ;
392
393#define	PXENV_TFTP_READ_FILE		0x0023
394typedef struct {
395	PXENV_STATUS_t	Status;
396	uint8_t		FileName[128];
397	uint32_t	BufferSize;
398	ADDR32_t	Buffer;
399	IP4_t		ServerIPAddress;
400	IP4_t		GatewayIPAdress;
401	IP4_t		McastIPAdress;
402	UDP_PORT_t	TFTPClntPort;
403	UDP_PORT_t	TFTPSrvPort;
404	uint16_t	TFTPOpenTimeOut;
405	uint16_t	TFTPReopenDelay;
406} PACKED t_PXENV_TFTP_READ_FILE;
407
408#define	PXENV_TFTP_GET_FSIZE		0x0025
409typedef struct {
410	PXENV_STATUS_t	Status;
411	IP4_t		ServerIPAddress;
412	IP4_t		GatewayIPAdress;
413	uint8_t		FileName[128];
414	uint32_t	FileSize;
415} PACKED t_PXENV_TFTP_GET_FSIZE;
416
417#define	PXENV_UDP_OPEN			0x0030
418typedef struct {
419	PXENV_STATUS_t	status;
420	IP4_t		src_ip;		/* IP address of this station */
421} PACKED t_PXENV_UDP_OPEN;
422
423#define	PXENV_UDP_CLOSE			0x0031
424typedef struct {
425	PXENV_STATUS_t	status;
426} PACKED t_PXENV_UDP_CLOSE;
427
428#define	PXENV_UDP_READ			0x0032
429typedef struct {
430	PXENV_STATUS_t	status;
431	IP4_t		src_ip;		/* IP of sender */
432	IP4_t		dest_ip;	/* Only accept packets sent to this IP */
433	UDP_PORT_t	s_port;		/* UDP source port of sender */
434	UDP_PORT_t	d_port;		/* Only accept packets sent to this port */
435	uint16_t	buffer_size;	/* Size of the packet buffer */
436	SEGOFF16_t	buffer;		/* SEG:OFF to the packet buffer */
437} PACKED t_PXENV_UDP_READ;
438
439#define	PXENV_UDP_WRITE			0x0033
440typedef struct {
441	PXENV_STATUS_t	status;
442	IP4_t		ip;		/* dest ip addr */
443	IP4_t		gw;		/* ip gateway */
444	UDP_PORT_t	src_port;	/* source udp port */
445	UDP_PORT_t	dst_port;	/* destination udp port */
446	uint16_t	buffer_size;	/* Size of the packet buffer */
447	SEGOFF16_t	buffer;		/* SEG:OFF to the packet buffer */
448} PACKED t_PXENV_UDP_WRITE;
449
450#define	PXENV_UNLOAD_STACK		0x0070
451typedef struct {
452	PXENV_STATUS_t	Status;
453	uint8_t		reserved[10];
454} PACKED t_PXENV_UNLOAD_STACK;
455
456
457#define	PXENV_GET_CACHED_INFO		0x0071
458typedef struct {
459	PXENV_STATUS_t	Status;
460	uint16_t	PacketType;	/* type (defined right here) */
461#	define PXENV_PACKET_TYPE_DHCP_DISCOVER  1
462#	define PXENV_PACKET_TYPE_DHCP_ACK       2
463#	define PXENV_PACKET_TYPE_BINL_REPLY     3
464	uint16_t	BufferSize;	/* max to copy, leave at 0 for pointer */
465	SEGOFF16_t	Buffer;		/* copy to, leave at 0 for pointer */
466	uint16_t	BufferLimit;	/* max size of buffer in BC dataseg ? */
467} PACKED t_PXENV_GET_CACHED_INFO;
468
469
470/* structure filled in by PXENV_GET_CACHED_INFO
471 * (how we determine which IP we downloaded the initial bootstrap from)
472 * words can't describe...
473 */
474typedef struct {
475	uint8_t		opcode;
476#	define BOOTP_REQ	1
477#	define BOOTP_REP	2
478	uint8_t		Hardware;	/* hardware type */
479	uint8_t		Hardlen;	/* hardware addr len */
480	uint8_t		Gatehops;	/* zero it */
481	uint32_t	ident;		/* random number chosen by client */
482	uint16_t	seconds;	/* seconds since did initial bootstrap */
483	uint16_t	Flags;		/* seconds since did initial bootstrap */
484#	define BOOTP_BCAST	0x8000		/* ? */
485	IP4_t		cip;		/* Client IP */
486	IP4_t		yip;		/* Your IP */
487	IP4_t		sip;		/* IP to use for next boot stage */
488	IP4_t		gip;		/* Relay IP ? */
489	MAC_ADDR	CAddr;		/* Client hardware address */
490	uint8_t		Sname[64];	/* Server's hostname (Optional) */
491	uint8_t		bootfile[128];	/* boot filename */
492	union {
493#		if 1
494#		define BOOTP_DHCPVEND  1024    /* DHCP extended vendor field size */
495#		else
496#		define BOOTP_DHCPVEND  312	/* DHCP standard vendor field size */
497#		endif
498		uint8_t		d[BOOTP_DHCPVEND];	/* raw array of vendor/dhcp options */
499		struct {
500			uint8_t		magic[4];	/* DHCP magic cookie */
501#			ifndef		VM_RFC1048
502#			define		VM_RFC1048	0x63825363L	/* ? */
503#			endif
504			uint32_t	flags;		/* bootp flags/opcodes */
505			uint8_t		pad[56];	/* I don't think intel knows what a
506							   union does... */
507		} v;
508	} vendor;
509} PACKED BOOTPLAYER;
510
511#define	PXENV_RESTART_TFTP		0x0073
512#define	t_PXENV_RESTART_TFTP		t_PXENV_TFTP_READ_FILE
513
514#define	PXENV_START_BASE		0x0075
515typedef struct {
516	PXENV_STATUS_t	Status;
517} PACKED t_PXENV_START_BASE;
518
519#define	PXENV_STOP_BASE			0x0076
520typedef struct {
521	PXENV_STATUS_t	Status;
522} PACKED t_PXENV_STOP_BASE;
523