Browse Source

Partial implementation of UNDI loader caller.

tags/v0.9.3
Michael Brown 17 years ago
parent
commit
9780fef360
4 changed files with 107 additions and 55 deletions
  1. 89
    4
      src/arch/i386/drivers/bus/pxedrv.c
  2. 1
    0
      src/arch/i386/include/bios.h
  3. 1
    1
      src/include/pxe.h
  4. 16
    50
      src/include/pxe_api.h

+ 89
- 4
src/arch/i386/drivers/bus/pxedrv.c View File

@@ -21,6 +21,7 @@
21 21
 #include <string.h>
22 22
 #include <pxe.h>
23 23
 #include <realmode.h>
24
+#include <bios.h>
24 25
 
25 26
 /** @file
26 27
  *
@@ -62,14 +63,15 @@ static int pxedrv_parse_pxeromid ( struct pxe_driver *pxedrv,
62 63
 	}
63 64
 
64 65
 	/* Fill in PXE driver loader fields */
65
-	pxedrv->loader.segment = pxedrv->rom_segment;
66
-	pxedrv->loader.offset = undiloader;
66
+	pxedrv->loader_entry.segment = pxedrv->rom_segment;
67
+	pxedrv->loader_entry.offset = undiloader;
67 68
 	pxedrv->code_size = undi_rom_id.CodeSize;
68 69
 	pxedrv->data_size = undi_rom_id.DataSize;
69 70
 
70 71
 	DBGC ( pxedrv, "PXEDRV %p has UNDI loader at %04x:%04x "
71
-	       "(code %04x data %04x)\n", pxedrv, pxedrv->loader.segment,
72
-	       pxedrv->loader.offset, pxedrv->code_size, pxedrv->data_size );
72
+	       "(code %04x data %04x)\n", pxedrv,
73
+	       pxedrv->loader_entry.segment, pxedrv->loader_entry.offset,
74
+	       pxedrv->code_size, pxedrv->data_size );
73 75
 	return 0;
74 76
 }
75 77
 
@@ -221,3 +223,86 @@ struct pxe_driver * pxedrv_find_pci_driver ( unsigned int vendor_id,
221 223
 	      vendor_id, device_id, rombase );
222 224
 	return NULL;
223 225
 }
226
+
227
+/** Parameter block for calling UNDI loader */
228
+static struct s_UNDI_LOADER __data16 ( undi_loader );
229
+#define undi_loader __use_data16 ( undi_loader )
230
+
231
+/** UNDI loader entry point */
232
+static SEGOFF16_t __data16 ( undi_loader_entry );
233
+#define undi_loader_entry __use_data16 ( undi_loader_entry )
234
+
235
+/**
236
+ * Call UNDI loader to create a pixie
237
+ *
238
+ * @v pxedrv		PXE driver
239
+ * @v pxe		PXE device to be created
240
+ * @v pci_busdevfn	PCI bus:dev.fn (PCI devices only), or 0
241
+ * @v isapnp_csn	ISAPnP Card Select Number, or -1U
242
+ * @v isapnp_read_port	ISAPnP read port, or -1U
243
+ * @ret rc		Return status code
244
+ */
245
+static int pxedrv_load ( struct pxe_driver *pxedrv, struct pxe_device *pxe,
246
+			 unsigned int pci_busdevfn, unsigned int isapnp_csn,
247
+			 unsigned int isapnp_read_port ) {
248
+	int discard;
249
+	uint16_t exit;
250
+	uint16_t fbms;
251
+	unsigned int fbms_seg;
252
+	int rc;
253
+
254
+	memset ( &undi_loader, 0, sizeof ( undi_loader ) );
255
+	undi_loader.AX = pci_busdevfn;
256
+	undi_loader.BX = isapnp_csn;
257
+	undi_loader.DX = isapnp_read_port;
258
+
259
+	/* Allocate base memory for PXE stack */
260
+	get_real ( fbms, BDA_SEG, BDA_FBMS );
261
+	fbms_seg = ( fbms << 6 );
262
+	fbms_seg -= ( ( pxedrv->data_size + 0x0f ) >> 4 );
263
+	undi_loader.UNDI_DS = fbms_seg;
264
+	fbms_seg -= ( ( pxedrv->code_size + 0x0f ) >> 4 );
265
+	undi_loader.UNDI_CS = fbms_seg;
266
+	DBGC ( pxedrv, "PXEDRV %p loading to CS %04x and DS %04x\n", pxedrv,
267
+	       undi_loader.UNDI_CS, undi_loader.UNDI_DS );
268
+
269
+	/* Call loader */
270
+	undi_loader_entry = pxedrv->loader_entry;
271
+	__asm__ __volatile__ ( REAL_CODE ( "pushw %%ds\n\t"
272
+					   "pushw %w0\n\t"
273
+					   "lcall *%c3\n\t"
274
+					   "addw $4, %%sp\n\t" )
275
+			       : "=a" ( exit ), "=r" ( discard )
276
+			       : "0" ( & __from_data16 ( undi_loader ) ),
277
+			         "p" ( & __from_data16 ( undi_loader_entry )));
278
+	if ( exit != PXENV_EXIT_SUCCESS ) {
279
+		rc = -undi_loader.Status;
280
+		if ( rc == 0 ) /* Paranoia */
281
+			rc = -EIO;
282
+		DBGC ( pxedrv, "PXEDRV %p loader failed: %s\n",
283
+		       strerror ( rc ) );
284
+		return rc;
285
+	}
286
+
287
+	/* Update free base memory counter */
288
+	fbms = ( fbms_seg >> 6 );
289
+	put_real ( fbms, BDA_SEG, BDA_FBMS );
290
+
291
+	/* Record location of pixie in PXE device structure */
292
+	pxe->pxenv = undi_loader.PXENVptr;
293
+	pxe->ppxe = undi_loader.PXEptr;
294
+	return 0;
295
+}
296
+
297
+/**
298
+ * Call UNDI loader to create a pixie
299
+ *
300
+ * @v pxedrv		PXE driver
301
+ * @v pxe		PXE device to be created
302
+ * @v pci_busdevfn	PCI bus:dev.fn
303
+ * @ret rc		Return status code
304
+ */
305
+int pxedrv_load_pci ( struct pxe_driver *pxedrv, struct pxe_device *pxe,
306
+		      unsigned int bus, unsigned int devfn ) {
307
+	return pxedrv_load ( pxedrv, pxe, ( ( bus << 8 ) | devfn ), -1U, -1U );
308
+}

+ 1
- 0
src/arch/i386/include/bios.h View File

@@ -2,6 +2,7 @@
2 2
 #define BIOS_H
3 3
 
4 4
 #define BDA_SEG 0x0040
5
+#define BDA_FBMS 0x0013
5 6
 #define BDA_NUM_DRIVES 0x0075
6 7
 
7 8
 extern unsigned long currticks ( void );

+ 1
- 1
src/include/pxe.h View File

@@ -155,7 +155,7 @@ struct pxe_driver {
155 155
 	/** ROM segment address */
156 156
 	unsigned int rom_segment;
157 157
 	/** UNDI loader entry point */
158
-	SEGOFF16_t loader;
158
+	SEGOFF16_t loader_entry;
159 159
 	/** Code segment size */
160 160
 	size_t code_size;
161 161
 	/** Data segment size */

+ 16
- 50
src/include/pxe_api.h View File

@@ -1562,54 +1562,20 @@ extern PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr );
1562 1562
  * @{
1563 1563
  */
1564 1564
 
1565
-/** The UNDI ROM ID structure */
1566
-struct s_UNDI_ROM_ID {
1567
-	/** Signature
1568
-	 *
1569
-	 * Contains the bytes 'U', 'N', 'D', 'I'.
1570
-	 */
1571
-	UINT32_t Signature;
1572
-	UINT8_t StructLength;		/**< Length of this structure */
1573
-	/** Checksum
1574
-	 *
1575
-	 * The byte checksum of this structure (using the length in
1576
-	 * #StructLength) must be zero.
1577
-	 */
1578
-	UINT8_t StructCksum;
1579
-	/** Revision of this structure
1580
-	 *
1581
-	 * For PXE version 2.1, this field must be zero.
1582
-	 */
1583
-	UINT8_t StructRev;
1584
-	/** UNDI revision
1585
-	 *
1586
-	 * UNDI revision, least significant byte first.  For UNDI
1587
-	 * version 2.1.0, this field will contain { 0x00, 0x01, 0x02 }.
1588
-	 */
1589
-	UINT8_t UNDIRev[3];
1590
-	/** UNDI loader routine entry point
1591
-	 *
1592
-	 * This is the entry point for calling undi_loader().
1593
-	 */
1594
-	UINT16_t UNDILoader;
1595
-	/** Minimum required stack segment size */
1596
-	UINT16_t StackSize;
1597
-	/** Minimum required data segment size */
1598
-	UINT16_t DataSize;
1599
-	/** Minimum required code segment size */
1600
-	UINT16_t CodeSize;
1601
-} PACKED;
1602
-
1603
-typedef struct s_UNDI_ROM_ID UNDI_ROM_ID_t;
1604
-
1605 1565
 /** Parameter block for undi_loader() */
1606 1566
 struct s_UNDI_LOADER {
1607
-	/** struct s_UNDI_LOADER starts with a struct s_PXENV_START_UNDI */
1608
-	union undi_loader_start_undi {
1609
-		PXENV_STATUS_t Status;		/**< PXE status code */
1610
-		/** Parameters to pass to pxenv_start_undi() */
1611
-		struct s_PXENV_START_UNDI start_undi;
1612
-	} u;
1567
+	/** PXE status code */
1568
+	PXENV_STATUS_t Status;
1569
+	/** %ax register as for PXENV_START_UNDI */
1570
+	UINT16_t AX;
1571
+	/** %bx register as for PXENV_START_UNDI */
1572
+	UINT16_t BX;
1573
+	/** %dx register as for PXENV_START_UNDI */
1574
+	UINT16_t DX;
1575
+	/** %di register as for PXENV_START_UNDI */
1576
+	OFF16_t DI;
1577
+	/** %es register as for PXENV_START_UNDI */
1578
+	SEGSEL_t ES;
1613 1579
 	/** UNDI data segment
1614 1580
 	 *
1615 1581
 	 * @note The PXE specification defines the type of this field
@@ -1617,7 +1583,7 @@ struct s_UNDI_LOADER {
1617 1583
 	 * equivalent anyway; for other architectures #SEGSEL_t makes
1618 1584
 	 * more sense.
1619 1585
 	 */
1620
-	SEGSEL_t	undi_ds;
1586
+	SEGSEL_t UNDI_DS;
1621 1587
 	/** UNDI code segment
1622 1588
 	 *
1623 1589
 	 * @note The PXE specification defines the type of this field
@@ -1625,11 +1591,11 @@ struct s_UNDI_LOADER {
1625 1591
 	 * equivalent anyway; for other architectures #SEGSEL_t makes
1626 1592
 	 * more sense.
1627 1593
 	 */
1628
-	SEGSEL_t	undi_cs;
1594
+	SEGSEL_t UNDI_CS;
1629 1595
 	/** Address of the !PXE structure (a struct s_PXE) */
1630
-	SEGOFF16_t	pxe_ptr;
1596
+	SEGOFF16_t PXEptr;
1631 1597
 	/** Address of the PXENV+ structure (a struct s_PXENV) */
1632
-	SEGOFF16_t	pxenv_ptr;
1598
+	SEGOFF16_t PXENVptr;
1633 1599
 } PACKED;
1634 1600
 
1635 1601
 typedef struct s_UNDI_LOADER UNDI_LOADER_t;

Loading…
Cancel
Save