summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2007-01-05 04:24:39 +0100
committerMichael Brown2007-01-05 04:24:39 +0100
commit9780fef360dc381ee6e4cd7e16f10990657eed83 (patch)
tree9b7a506c6c82087f0096c6c49375d5503da8a028
parentAdd PXE driver-scanning code, capable of locating all PXE ROMs in a system (diff)
downloadipxe-9780fef360dc381ee6e4cd7e16f10990657eed83.tar.gz
ipxe-9780fef360dc381ee6e4cd7e16f10990657eed83.tar.xz
ipxe-9780fef360dc381ee6e4cd7e16f10990657eed83.zip
Partial implementation of UNDI loader caller.
-rw-r--r--src/arch/i386/drivers/bus/pxedrv.c93
-rw-r--r--src/arch/i386/include/bios.h1
-rw-r--r--src/include/pxe.h2
-rw-r--r--src/include/pxe_api.h66
4 files changed, 107 insertions, 55 deletions
diff --git a/src/arch/i386/drivers/bus/pxedrv.c b/src/arch/i386/drivers/bus/pxedrv.c
index 4e4325740..3e663c759 100644
--- a/src/arch/i386/drivers/bus/pxedrv.c
+++ b/src/arch/i386/drivers/bus/pxedrv.c
@@ -21,6 +21,7 @@
#include <string.h>
#include <pxe.h>
#include <realmode.h>
+#include <bios.h>
/** @file
*
@@ -62,14 +63,15 @@ static int pxedrv_parse_pxeromid ( struct pxe_driver *pxedrv,
}
/* Fill in PXE driver loader fields */
- pxedrv->loader.segment = pxedrv->rom_segment;
- pxedrv->loader.offset = undiloader;
+ pxedrv->loader_entry.segment = pxedrv->rom_segment;
+ pxedrv->loader_entry.offset = undiloader;
pxedrv->code_size = undi_rom_id.CodeSize;
pxedrv->data_size = undi_rom_id.DataSize;
DBGC ( pxedrv, "PXEDRV %p has UNDI loader at %04x:%04x "
- "(code %04x data %04x)\n", pxedrv, pxedrv->loader.segment,
- pxedrv->loader.offset, pxedrv->code_size, pxedrv->data_size );
+ "(code %04x data %04x)\n", pxedrv,
+ pxedrv->loader_entry.segment, pxedrv->loader_entry.offset,
+ pxedrv->code_size, pxedrv->data_size );
return 0;
}
@@ -221,3 +223,86 @@ struct pxe_driver * pxedrv_find_pci_driver ( unsigned int vendor_id,
vendor_id, device_id, rombase );
return NULL;
}
+
+/** Parameter block for calling UNDI loader */
+static struct s_UNDI_LOADER __data16 ( undi_loader );
+#define undi_loader __use_data16 ( undi_loader )
+
+/** UNDI loader entry point */
+static SEGOFF16_t __data16 ( undi_loader_entry );
+#define undi_loader_entry __use_data16 ( undi_loader_entry )
+
+/**
+ * Call UNDI loader to create a pixie
+ *
+ * @v pxedrv PXE driver
+ * @v pxe PXE device to be created
+ * @v pci_busdevfn PCI bus:dev.fn (PCI devices only), or 0
+ * @v isapnp_csn ISAPnP Card Select Number, or -1U
+ * @v isapnp_read_port ISAPnP read port, or -1U
+ * @ret rc Return status code
+ */
+static int pxedrv_load ( struct pxe_driver *pxedrv, struct pxe_device *pxe,
+ unsigned int pci_busdevfn, unsigned int isapnp_csn,
+ unsigned int isapnp_read_port ) {
+ int discard;
+ uint16_t exit;
+ uint16_t fbms;
+ unsigned int fbms_seg;
+ int rc;
+
+ memset ( &undi_loader, 0, sizeof ( undi_loader ) );
+ undi_loader.AX = pci_busdevfn;
+ undi_loader.BX = isapnp_csn;
+ undi_loader.DX = isapnp_read_port;
+
+ /* Allocate base memory for PXE stack */
+ get_real ( fbms, BDA_SEG, BDA_FBMS );
+ fbms_seg = ( fbms << 6 );
+ fbms_seg -= ( ( pxedrv->data_size + 0x0f ) >> 4 );
+ undi_loader.UNDI_DS = fbms_seg;
+ fbms_seg -= ( ( pxedrv->code_size + 0x0f ) >> 4 );
+ undi_loader.UNDI_CS = fbms_seg;
+ DBGC ( pxedrv, "PXEDRV %p loading to CS %04x and DS %04x\n", pxedrv,
+ undi_loader.UNDI_CS, undi_loader.UNDI_DS );
+
+ /* Call loader */
+ undi_loader_entry = pxedrv->loader_entry;
+ __asm__ __volatile__ ( REAL_CODE ( "pushw %%ds\n\t"
+ "pushw %w0\n\t"
+ "lcall *%c3\n\t"
+ "addw $4, %%sp\n\t" )
+ : "=a" ( exit ), "=r" ( discard )
+ : "0" ( & __from_data16 ( undi_loader ) ),
+ "p" ( & __from_data16 ( undi_loader_entry )));
+ if ( exit != PXENV_EXIT_SUCCESS ) {
+ rc = -undi_loader.Status;
+ if ( rc == 0 ) /* Paranoia */
+ rc = -EIO;
+ DBGC ( pxedrv, "PXEDRV %p loader failed: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ /* Update free base memory counter */
+ fbms = ( fbms_seg >> 6 );
+ put_real ( fbms, BDA_SEG, BDA_FBMS );
+
+ /* Record location of pixie in PXE device structure */
+ pxe->pxenv = undi_loader.PXENVptr;
+ pxe->ppxe = undi_loader.PXEptr;
+ return 0;
+}
+
+/**
+ * Call UNDI loader to create a pixie
+ *
+ * @v pxedrv PXE driver
+ * @v pxe PXE device to be created
+ * @v pci_busdevfn PCI bus:dev.fn
+ * @ret rc Return status code
+ */
+int pxedrv_load_pci ( struct pxe_driver *pxedrv, struct pxe_device *pxe,
+ unsigned int bus, unsigned int devfn ) {
+ return pxedrv_load ( pxedrv, pxe, ( ( bus << 8 ) | devfn ), -1U, -1U );
+}
diff --git a/src/arch/i386/include/bios.h b/src/arch/i386/include/bios.h
index 4b4b9d25c..630a898b3 100644
--- a/src/arch/i386/include/bios.h
+++ b/src/arch/i386/include/bios.h
@@ -2,6 +2,7 @@
#define BIOS_H
#define BDA_SEG 0x0040
+#define BDA_FBMS 0x0013
#define BDA_NUM_DRIVES 0x0075
extern unsigned long currticks ( void );
diff --git a/src/include/pxe.h b/src/include/pxe.h
index e85e7e270..003ebf125 100644
--- a/src/include/pxe.h
+++ b/src/include/pxe.h
@@ -155,7 +155,7 @@ struct pxe_driver {
/** ROM segment address */
unsigned int rom_segment;
/** UNDI loader entry point */
- SEGOFF16_t loader;
+ SEGOFF16_t loader_entry;
/** Code segment size */
size_t code_size;
/** Data segment size */
diff --git a/src/include/pxe_api.h b/src/include/pxe_api.h
index 7256c57e5..e64413254 100644
--- a/src/include/pxe_api.h
+++ b/src/include/pxe_api.h
@@ -1562,54 +1562,20 @@ extern PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr );
* @{
*/
-/** The UNDI ROM ID structure */
-struct s_UNDI_ROM_ID {
- /** Signature
- *
- * Contains the bytes 'U', 'N', 'D', 'I'.
- */
- UINT32_t Signature;
- UINT8_t StructLength; /**< Length of this structure */
- /** Checksum
- *
- * The byte checksum of this structure (using the length in
- * #StructLength) must be zero.
- */
- UINT8_t StructCksum;
- /** Revision of this structure
- *
- * For PXE version 2.1, this field must be zero.
- */
- UINT8_t StructRev;
- /** UNDI revision
- *
- * UNDI revision, least significant byte first. For UNDI
- * version 2.1.0, this field will contain { 0x00, 0x01, 0x02 }.
- */
- UINT8_t UNDIRev[3];
- /** UNDI loader routine entry point
- *
- * This is the entry point for calling undi_loader().
- */
- UINT16_t UNDILoader;
- /** Minimum required stack segment size */
- UINT16_t StackSize;
- /** Minimum required data segment size */
- UINT16_t DataSize;
- /** Minimum required code segment size */
- UINT16_t CodeSize;
-} PACKED;
-
-typedef struct s_UNDI_ROM_ID UNDI_ROM_ID_t;
-
/** Parameter block for undi_loader() */
struct s_UNDI_LOADER {
- /** struct s_UNDI_LOADER starts with a struct s_PXENV_START_UNDI */
- union undi_loader_start_undi {
- PXENV_STATUS_t Status; /**< PXE status code */
- /** Parameters to pass to pxenv_start_undi() */
- struct s_PXENV_START_UNDI start_undi;
- } u;
+ /** PXE status code */
+ PXENV_STATUS_t Status;
+ /** %ax register as for PXENV_START_UNDI */
+ UINT16_t AX;
+ /** %bx register as for PXENV_START_UNDI */
+ UINT16_t BX;
+ /** %dx register as for PXENV_START_UNDI */
+ UINT16_t DX;
+ /** %di register as for PXENV_START_UNDI */
+ OFF16_t DI;
+ /** %es register as for PXENV_START_UNDI */
+ SEGSEL_t ES;
/** UNDI data segment
*
* @note The PXE specification defines the type of this field
@@ -1617,7 +1583,7 @@ struct s_UNDI_LOADER {
* equivalent anyway; for other architectures #SEGSEL_t makes
* more sense.
*/
- SEGSEL_t undi_ds;
+ SEGSEL_t UNDI_DS;
/** UNDI code segment
*
* @note The PXE specification defines the type of this field
@@ -1625,11 +1591,11 @@ struct s_UNDI_LOADER {
* equivalent anyway; for other architectures #SEGSEL_t makes
* more sense.
*/
- SEGSEL_t undi_cs;
+ SEGSEL_t UNDI_CS;
/** Address of the !PXE structure (a struct s_PXE) */
- SEGOFF16_t pxe_ptr;
+ SEGOFF16_t PXEptr;
/** Address of the PXENV+ structure (a struct s_PXENV) */
- SEGOFF16_t pxenv_ptr;
+ SEGOFF16_t PXENVptr;
} PACKED;
typedef struct s_UNDI_LOADER UNDI_LOADER_t;