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