Partial implementation of UNDI loader caller.
authorMichael Brown <mcb30@etherboot.org>
Fri, 5 Jan 2007 03:24:39 +0000 (03:24 +0000)
committerMichael Brown <mcb30@etherboot.org>
Fri, 5 Jan 2007 03:24:39 +0000 (03:24 +0000)
src/arch/i386/drivers/bus/pxedrv.c
src/arch/i386/include/bios.h
src/include/pxe.h
src/include/pxe_api.h

index 4e43257..3e663c7 100644 (file)
@@ -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 );
+}
index 4b4b9d2..630a898 100644 (file)
@@ -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 );
index e85e7e2..003ebf1 100644 (file)
@@ -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 */
index 7256c57..e644132 100644 (file)
@@ -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;