mirror of
https://github.com/xcat2/xNBA.git
synced 2025-01-31 05:17:34 +00:00
Partial implementation of UNDI loader caller.
This commit is contained in:
parent
0638945c7e
commit
9780fef360
@ -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 );
|
||||
}
|
||||
|
@ -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 );
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user