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