Kaynağa Gözat

Added (not yet tested) PXE API entry point and support functions.

tags/v0.9.3
Michael Brown 18 yıl önce
ebeveyn
işleme
18c112d205

+ 108
- 0
src/arch/i386/interface/pxe/pxe_call.c Dosyayı Görüntüle

@@ -18,6 +18,7 @@
18 18
 
19 19
 #include <gpxe/uaccess.h>
20 20
 #include <registers.h>
21
+#include <biosint.h>
21 22
 #include <pxe.h>
22 23
 
23 24
 /** @file
@@ -25,6 +26,21 @@
25 26
  * PXE API entry point
26 27
  */
27 28
 
29
+/** Vector for chaining INT 1A */
30
+extern struct segoff __text16 ( pxe_int_1a_vector );
31
+#define pxe_int_1a_vector __use_text16 ( pxe_int_1a_vector )
32
+
33
+/** INT 1A handler */
34
+extern void pxe_int_1a ( void );
35
+
36
+/** !PXE structure */
37
+extern struct s_PXE __text16 ( pxe );
38
+#define pxe __use_text16 ( pxe )
39
+
40
+/** PXENV+ structure */
41
+extern struct s_PXENV __text16 ( pxenv );
42
+#define pxenv __use_text16 ( pxenv )
43
+
28 44
 /** A function pointer to hold any PXE API call
29 45
  *
30 46
  * Used by pxe_api_call() to avoid large swathes of duplicated code.
@@ -288,3 +304,95 @@ void pxe_api_call ( struct i386_all_regs *ix86 ) {
288 304
 	copy_to_user ( parameters, 0, &pxenv_any, param_len );
289 305
 	ix86->regs.ax = ret;
290 306
 }
307
+
308
+/**
309
+ * Hook INT 1A for PXE
310
+ *
311
+ */
312
+void pxe_hook_int ( void ) {
313
+	hook_bios_interrupt ( 0x1a, ( unsigned int ) pxe_int_1a,
314
+			      &pxe_int_1a_vector );
315
+}
316
+
317
+/**
318
+ * Unhook INT 1A for PXE
319
+ *
320
+ * @ret rc		Return status code
321
+ */
322
+int pxe_unhook_int ( void ) {
323
+	return unhook_bios_interrupt ( 0x1a, ( unsigned int ) pxe_int_1a,
324
+				       &pxe_int_1a_vector );
325
+}
326
+
327
+/**
328
+ * Calculate byte checksum as used by PXE
329
+ *
330
+ * @v data		Data
331
+ * @v size		Length of data
332
+ * @ret sum		Checksum
333
+ */
334
+static uint8_t pxe_checksum ( void *data, size_t size ) {
335
+	uint8_t *bytes = data;
336
+	uint8_t sum = 0;
337
+
338
+	while ( size-- ) {
339
+		sum += *bytes++;
340
+	}
341
+	return sum;
342
+}
343
+
344
+/**
345
+ * Initialise PXE stack
346
+ *
347
+ */
348
+void init_pxe ( void ) {
349
+	uint32_t rm_cs_phys = ( rm_cs << 4 );
350
+	uint32_t rm_ds_phys = ( rm_ds << 4 );
351
+
352
+	/* Fill in missing segment fields */
353
+	pxe.EntryPointSP.segment = rm_cs;
354
+	pxe.EntryPointESP.segment = rm_cs;
355
+	pxe.Stack.segment_address = rm_ds;
356
+	pxe.Stack.Physical_address = rm_ds_phys;
357
+	pxe.UNDIData.segment_address = rm_ds;
358
+	pxe.UNDIData.Physical_address = rm_ds_phys;
359
+	pxe.UNDICode.segment_address = rm_cs;
360
+	pxe.UNDICode.Physical_address = rm_cs_phys;
361
+	pxe.UNDICodeWrite.segment_address = rm_cs;
362
+	pxe.UNDICodeWrite.Physical_address = rm_cs_phys;
363
+	pxenv.RMEntry.segment = rm_cs;
364
+	pxenv.StackSeg = rm_ds;
365
+	pxenv.UNDIDataSeg = rm_ds;
366
+	pxenv.UNDICodeSeg = rm_cs;
367
+	pxenv.PXEPtr.segment = rm_cs;
368
+
369
+	/* Update checksums */
370
+	pxe.StructCksum -= pxe_checksum ( &pxe, sizeof ( pxe ) );
371
+	pxenv.Checksum -= pxe_checksum ( &pxenv, sizeof ( pxenv ) );
372
+}
373
+
374
+/**
375
+ * Boot via PXE NBP
376
+ *
377
+ * @ret rc		Return status code
378
+ */
379
+int pxe_boot ( void ) {
380
+	int discard_b, discard_c;
381
+	uint16_t rc;
382
+
383
+	/* Ensure that PXE stack is ready to use */
384
+	init_pxe();
385
+	pxe_hook_int();
386
+
387
+	/* Far call to PXE NBP */
388
+	__asm__ __volatile__ ( REAL_CODE ( "pushw %%cx\n\t"
389
+					   "pushw %%ax\n\t"
390
+					   "movw %%cx, %%es\n\t"
391
+					   "lcall $0, $0x7c00\n\t" )
392
+			       : "=a" ( rc ), "=b" ( discard_b ),
393
+			         "=c" ( discard_c )
394
+			       :  "a" ( &pxe ), "b" ( &pxenv ), "c" ( rm_cs )
395
+			       : "edx", "esi", "edi", "ebp", "memory" );
396
+
397
+	return rc;
398
+}

+ 192
- 0
src/arch/i386/interface/pxe/pxe_entry.S Dosyayı Görüntüle

@@ -0,0 +1,192 @@
1
+/*
2
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ *
18
+ */
19
+
20
+	.arch i386
21
+	.section ".text16", "awx", @progbits
22
+	.section ".text16.data", "aw", @progbits
23
+	.section ".data16", "aw", @progbits
24
+
25
+/****************************************************************************
26
+ * !PXE structure
27
+ ****************************************************************************
28
+ */
29
+	.section ".text16.data"
30
+	.globl pxe
31
+pxe:
32
+	.ascii "!PXE"			/* Signature */
33
+	.byte pxe_length		/* StructLength */
34
+	.byte 0				/* StructCksum */
35
+	.byte 0				/* StructRev */
36
+	.byte 0				/* reserved_1 */
37
+	.word 0, 0			/* UNDIROMID */
38
+	.word 0, 0			/* BaseROMID */
39
+	.word pxe_entry_sp, 0		/* EntryPointSP */
40
+	.word pxe_entry_esp, 0		/* EntryPointESP */
41
+	.word -1, -1			/* StatusCallout */
42
+	.byte 0				/* reserved_2 */
43
+	.byte SegDescCnt		/* SegDescCnt */
44
+	.word 0				/* FirstSelector */
45
+pxe_segments:
46
+	.word 0, 0, 0, _data16_size	/* Stack */
47
+	.word 0, 0, 0, _data16_size	/* UNDIData */
48
+	.word 0, 0, 0, _text16_size	/* UNDICode */
49
+	.word 0, 0, 0, _text16_size	/* UNDICodeWrite */
50
+	.word 0, 0, 0, 0		/* BC_Data */
51
+	.word 0, 0, 0, 0		/* BC_Code */
52
+	.word 0, 0, 0, 0		/* BC_CodeWrite */
53
+	.equ	SegDescCnt, ( ( . - pxe_segments ) / 8 )
54
+	.equ	pxe_length, . - pxe
55
+	.size	pxe, . - pxe
56
+
57
+/****************************************************************************
58
+ * PXENV+ structure
59
+ ****************************************************************************
60
+ */
61
+	.section ".text16.data"
62
+	.globl pxenv
63
+pxenv:
64
+	.ascii "PXENV+"			/* Signature */
65
+	.word 0x0201			/* Version */
66
+	.byte pxenv_length		/* Length */
67
+	.byte 0				/* Checksum */
68
+	.word pxenv_entry, 0		/* RMEntry */
69
+	.long 0				/* PMEntry */
70
+	.word 0				/* PMSelector */
71
+	.word 0				/* StackSeg */
72
+	.word _data16_size		/* StackSize */
73
+	.word 0				/* BC_CodeSeg */
74
+	.word 0				/* BC_CodeSize */
75
+	.word 0				/* BC_DataSeg */
76
+	.word 0				/* BC_DataSize */
77
+	.word 0				/* UNDIDataSeg */
78
+	.word _data16_size		/* UNDIDataSize */
79
+	.word 0				/* UNDICodeSeg */
80
+	.word _text16_size		/* UNDICodeSize */
81
+	.word pxe, 0			/* PXEPtr */
82
+	.equ	pxenv_length, . - pxenv
83
+	.size	pxenv, . - pxenv
84
+ 
85
+/****************************************************************************
86
+ * pxenv_entry (16-bit far call)
87
+ *
88
+ * PXE API call PXENV+ entry point
89
+ *
90
+ * Parameters:
91
+ *   %es:di : Far pointer to PXE parameter structure
92
+ *   %bx : PXE API call
93
+ * Returns:
94
+ *   %ax : PXE exit status
95
+ * Corrupts:
96
+ *   none
97
+ ****************************************************************************
98
+ */
99
+	.section ".text16"
100
+	.code16
101
+pxenv_entry:
102
+	pushl	$pxe_api_call
103
+	pushw	%cs
104
+	call	prot_call
105
+	addl	$4, %esp
106
+	lret
107
+	.size	pxenv_entry, . - pxenv_entry
108
+
109
+/****************************************************************************
110
+ * pxe_entry
111
+ *
112
+ * PXE API call !PXE entry point
113
+ *
114
+ * Parameters:
115
+ *   stack : Far pointer to PXE parameter structure
116
+ *   stack : PXE API call
117
+ * Returns:
118
+ *   %ax : PXE exit status
119
+ * Corrupts:
120
+ *   none
121
+ ****************************************************************************
122
+ */
123
+	.section ".text16"
124
+	.code16
125
+pxe_entry:
126
+pxe_entry_sp:
127
+	/* Preserve original %esp */
128
+	pushl	%esp
129
+	/* Zero high word of %esp to allow use of common code */
130
+	movzwl	%sp, %esp
131
+	jmp	pxe_entry_common
132
+pxe_entry_esp:
133
+	/* Preserve %esp to match behaviour of pxe_entry_sp */
134
+	pushl	%esp
135
+pxe_entry_common:
136
+	/* Save PXENV+ API call registers */
137
+	pushw	%es
138
+	pushw	%di
139
+	pushw	%bx
140
+	/* Load !PXE parameters from stack into PXENV+ registers */
141
+	movw	16(%esp), %bx
142
+	movw	%bx, %es
143
+	movw	14(%esp), %di
144
+	movw	12(%esp), %bx
145
+	/* Make call as for PXENV+ */
146
+	pushw	%cs
147
+	call	pxenv_entry
148
+	/* Restore PXENV+ registers */
149
+	popw	%bx
150
+	popw	%di
151
+	popw	%es
152
+	/* Restore original %esp and return */
153
+	popl	%esp
154
+	lret
155
+	.size	pxe_entry, . - pxe_entry
156
+
157
+/****************************************************************************
158
+ * pxe_int_1a
159
+ *
160
+ * PXE INT 1A handler
161
+ *
162
+ * Parameters:
163
+ *   %ax : 0x5650
164
+ * Returns:
165
+ *   %ax : 0x564e
166
+ *   %es:bx : Far pointer to the PXENV+ structure
167
+ *   CF cleared
168
+ * Corrupts:
169
+ *   none
170
+ ****************************************************************************
171
+ */
172
+	.section ".text16"
173
+	.code16
174
+pxe_int_1a:
175
+	pushfw
176
+	cmpw	$0x5650, %ax
177
+	jne	1f
178
+	/* INT 1A,5650 - PXE installation check */
179
+	pushw	%cs
180
+	popw	%es
181
+	movw	$pxenv, %bx
182
+	movw	$0x564e, %ax
183
+	popfw
184
+	clc
185
+	lret	$2
186
+1:	/* INT 1A,other - pass through */
187
+	popfw
188
+	ljmp	*%cs:pxe_int_1a_vector
189
+
190
+	.section ".text16.data"
191
+	.globl	pxe_int_1a_vector
192
+pxe_int_1a_vector:	.long 0

Loading…
İptal
Kaydet