Browse Source

Add (untested) UNDI loader C-level implementation.

tags/v0.9.3
Michael Brown 17 years ago
parent
commit
dca470cb21
3 changed files with 64 additions and 74 deletions
  1. 25
    0
      src/arch/i386/interface/pxe/pxe_call.c
  2. 22
    56
      src/interface/pxe/pxe_loader.c
  3. 17
    18
      src/interface/pxe/pxe_preboot.c

+ 25
- 0
src/arch/i386/interface/pxe/pxe_call.c View File

@@ -298,6 +298,31 @@ void pxe_api_call ( struct i386_all_regs *ix86 ) {
298 298
 	ix86->regs.ax = ret;
299 299
 }
300 300
 
301
+/**
302
+ * Dispatch PXE loader call
303
+ *
304
+ * @v es:di		Address of PXE parameter block
305
+ * @ret ax		PXE exit code
306
+ */
307
+void pxe_loader_call ( struct i386_all_regs *ix86 ) {
308
+	userptr_t uparams = real_to_user ( ix86->segs.es, ix86->regs.di );
309
+	struct s_UNDI_LOADER params;
310
+	PXENV_EXIT_t ret;
311
+
312
+	/* Copy parameter block from caller */
313
+	copy_from_user ( &params, uparams, 0, sizeof ( params ) );
314
+
315
+	/* Set default status in case child routine fails to do so */
316
+	params.Status = PXENV_STATUS_FAILURE;
317
+
318
+	/* Call UNDI loader */
319
+	ret = undi_loader ( &params );
320
+
321
+	/* Copy modified parameter block back to caller and return */
322
+	copy_to_user ( uparams, 0, &params, sizeof ( params ) );
323
+	ix86->regs.ax = ret;
324
+}
325
+
301 326
 /**
302 327
  * Hook INT 1A for PXE
303 328
  *

+ 22
- 56
src/interface/pxe/pxe_loader.c View File

@@ -1,11 +1,5 @@
1
-/** @file
2
- *
3
- * PXE UNDI loader
4
- *
5
- */
6
-
7 1
 /*
8
- * Copyright (C) 2004 Michael Brown <mbrown@fensystems.co.uk>.
2
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
9 3
  *
10 4
  * This program is free software; you can redistribute it and/or
11 5
  * modify it under the terms of the GNU General Public License as
@@ -22,65 +16,37 @@
22 16
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 17
  */
24 18
 
25
-#warning "Currently broken"
26
-#if 0
19
+#include <gpxe/init.h>
27 20
 #include "pxe.h"
21
+#include "pxe_call.h"
28 22
 
29
-/* PXENV_UNDI_LOADER
23
+/** @file
24
+ *
25
+ * PXE UNDI loader
30 26
  *
31
- * Status: working
27
+ */
28
+
29
+/* PXENV_UNDI_LOADER
32 30
  *
33
- * NOTE: This is not a genuine PXE API call; the loader has a separate
34
- * entry point.  However, to simplify the mapping of the PXE API to
35
- * the internal Etherboot API, both are directed through the same
36
- * interface.
37 31
  */
38 32
 PXENV_EXIT_t undi_loader ( struct s_UNDI_LOADER *undi_loader ) {
39
-	uint32_t loader_phys = virt_to_phys ( undi_loader );
40
-
41
-	DBG ( "PXENV_UNDI_LOADER" );
42
-	
43
-	/* Set UNDI DS as our real-mode stack */
44
-	use_undi_ds_for_rm_stack ( undi_loader->undi_ds );
45
-
46
-	/* FIXME: These lines are borrowed from main.c.  There should
47
-	 * probably be a single initialise() function that does all
48
-	 * this, but it's currently split interestingly between main()
49
-	 * and main_loop()...
50
-	 */
51
-
52
-
53
-	/* CHECKME: Our init functions have probably already been
54
-	   called by the ROM prefix's call to setup(), haven't
55
-	   they? */
56
-
57 33
 
34
+	DBG ( "[PXENV_UNDI_LOADER]" );
58 35
 
59
-	/* We have relocated; the loader pointer is now invalid */
60
-	undi_loader = phys_to_virt ( loader_phys );
36
+	/* Perform one-time initialisation (e.g. heap) */
37
+	initialise();
61 38
 
62
-	/* Install PXE stack to area specified by NBP */
63
-	install_pxe_stack ( VIRTUAL ( undi_loader->undi_cs, 0 ) );
64
-	
65
-	/* Call pxenv_start_undi to set parameters.  Why the hell PXE
66
-	 * requires these parameters to be provided twice is beyond
67
-	 * the wit of any sane man.  Don't worry if it fails; the NBP
68
-	 * should call PXENV_START_UNDI separately anyway.
69
-	 */
70
-	pxenv_start_undi ( &undi_loader->u.start_undi );
71
-	/* Unhook stack; the loader is not meant to hook int 1a etc,
72
-	 * but the call the pxenv_start_undi will cause it to happen.
73
-	 */
39
+	/* Set up PXE data structures */
40
+	pxe_init_structures();
74 41
 
75
-	/* FIXME: can't use ENSURE_CAN_UNLOAD() thanks to newer gcc's
76
-	 * barfing on unnamed struct/unions. */
77
-	/*	ENSURE_CAN_UNLOAD ( undi_loader ); */
42
+	/* Fill in UNDI loader structure */
43
+	undi_loader->PXEptr.segment = rm_ds;
44
+	undi_loader->PXEptr.offset =
45
+		( ( unsigned ) & __from_text16 ( ppxe ) );
46
+	undi_loader->PXENVptr.segment = rm_ds;
47
+	undi_loader->PXENVptr.offset =
48
+		( ( unsigned ) & __from_text16 ( pxenv ) );
78 49
 
79
-	/* Fill in addresses of !PXE and PXENV+ structures */
80
-	PTR_TO_SEGOFF16 ( &pxe_stack->pxe, undi_loader->pxe_ptr );
81
-	PTR_TO_SEGOFF16 ( &pxe_stack->pxenv, undi_loader->pxenv_ptr );
82
-	
83
-	undi_loader->u.Status = PXENV_STATUS_SUCCESS;
50
+	undi_loader->Status = PXENV_STATUS_SUCCESS;
84 51
 	return PXENV_EXIT_SUCCESS;
85 52
 }
86
-#endif

+ 17
- 18
src/interface/pxe/pxe_preboot.c View File

@@ -45,6 +45,9 @@
45 45
  */
46 46
 static char *pxe_ris_filename = NULL;
47 47
 
48
+/* Avoid dragging in isapnp.o unnecessarily */
49
+uint16_t isapnp_read_port;
50
+
48 51
 /**
49 52
  * UNLOAD BASE CODE STACK
50 53
  *
@@ -180,9 +183,6 @@ PXENV_EXIT_t pxenv_restart_tftp ( struct s_PXENV_TFTP_READ_FILE
180 183
  * Status: working
181 184
  */
182 185
 PXENV_EXIT_t pxenv_start_undi ( struct s_PXENV_START_UNDI *start_undi ) {
183
-	unsigned int isapnp_read_port;
184
-	unsigned int isapnp_csn;
185
-	unsigned int pci_busdevfn;
186 186
 	unsigned int bus_type;
187 187
 	unsigned int location;
188 188
 	struct net_device *netdev;
@@ -190,26 +190,25 @@ PXENV_EXIT_t pxenv_start_undi ( struct s_PXENV_START_UNDI *start_undi ) {
190 190
 	DBG ( "PXENV_START_UNDI %04x:%04x:%04x",
191 191
 	      start_undi->AX, start_undi->BX, start_undi->DX );
192 192
 
193
-	/* Probe for devices, etc. */
194
-	startup();
195
-
196
-	/* Determine bus type and location */
197
-	isapnp_read_port = start_undi->DX;
198
-	isapnp_csn = start_undi->BX;
199
-	pci_busdevfn = start_undi->AX;
200
-
201
-	/* Use a heuristic to decide whether we are PCI or ISAPnP */
202
-	if ( ( isapnp_read_port >= ISAPNP_READ_PORT_MIN ) &&
203
-	     ( isapnp_read_port <= ISAPNP_READ_PORT_MAX ) &&
204
-	     ( isapnp_csn >= ISAPNP_CSN_MIN ) &&
205
-	     ( isapnp_csn <= ISAPNP_CSN_MAX ) ) {
193
+	/* Determine bus type and location.  Use a heuristic to decide
194
+	 * whether we are PCI or ISAPnP
195
+	 */
196
+	if ( ( start_undi->DX >= ISAPNP_READ_PORT_MIN ) &&
197
+	     ( start_undi->DX <= ISAPNP_READ_PORT_MAX ) &&
198
+	     ( start_undi->BX >= ISAPNP_CSN_MIN ) &&
199
+	     ( start_undi->BX <= ISAPNP_CSN_MAX ) ) {
206 200
 		bus_type = BUS_TYPE_ISAPNP;
207
-		location = isapnp_csn;
201
+		location = start_undi->BX;
202
+		/* Record ISAPnP read port for use by isapnp.c */
203
+		isapnp_read_port = start_undi->DX;
208 204
 	} else {
209 205
 		bus_type = BUS_TYPE_PCI;
210
-		location = pci_busdevfn;
206
+		location = start_undi->AX;
211 207
 	}
212 208
 
209
+	/* Probe for devices, etc. */
210
+	startup();
211
+
213 212
 	/* Look for a matching net device */
214 213
 	netdev = find_netdev_by_location ( bus_type, location );
215 214
 	if ( ! netdev ) {

Loading…
Cancel
Save