Bring support in for Intel Wired for Management 1.1 (PXE 0.99 and

below).  This did not work previously because interrupts were
disabled when PXE calls were being made, and they must be enabled.
This should also allow us to be compliant with all newer PXE rom's
from Intel.

For PXE 0.99, this has been tested using the Intel N440BX motherboard
and I am confident it will work on the Intel L440GX motherboard.

Lots of help/information from: jhb, peter

I would like to thank Michael Johnston <michael.johnston@intel.com>,
Mike Henry <mike.henry@intel.com>, and all the other PXE developers
at Intel for their help, and information in helping solve this
problem.
This commit is contained in:
ps 2000-04-26 07:38:40 +00:00
parent d56a3c0de0
commit 7fbc9ae671
2 changed files with 96 additions and 45 deletions

View File

@ -70,7 +70,9 @@ static int pxe_sock = -1;
static int pxe_opens = 0;
void pxe_enable(void *pxeinfo);
void pxe_call(int func);
static void (*pxe_call)(int func);
static void pxenv_call(int func);
static void bangpxe_call(int func);
static int pxe_init(void);
static int pxe_strategy(void *devdata, int flag, daddr_t dblk,
@ -92,9 +94,12 @@ static void pxe_netif_end(struct netif *nif);
extern struct netif_stats pxe_st[];
extern struct in_addr rootip;
extern char rootpath[FNAME_SIZE];
extern u_int16_t __pxeseg;
extern u_int16_t __pxeoff;
extern void __h0h0magic(void);
extern u_int16_t __bangpxeseg;
extern u_int16_t __bangpxeoff;
extern void __bangpxeentry(void);
extern u_int16_t __pxenvseg;
extern u_int16_t __pxenvoff;
extern void __pxenventry(void);
struct netif_dif pxe_ifs[] = {
/* dif_unit dif_nsel dif_stats dif_private */
@ -140,7 +145,10 @@ struct devsw pxedisk = {
void
pxe_enable(void *pxeinfo)
{
pxenv_p = (pxenv_t *)pxeinfo;
pxenv_p = (pxenv_t *)pxeinfo;
pxe_p = (pxe_t *)PTOV(pxenv_p->PXEPtr.segment * 16 +
pxenv_p->PXEPtr.offset);
pxe_call = NULL;
}
/*
@ -185,34 +193,42 @@ pxe_init(void)
return (0);
}
if (pxenv_p->Version < 0x0201) {
printf("PXENV+ is not supported.\n");
return (0);
/*
* PXENV+ passed, so use that if !PXE is not available or
* the checksum fails.
*/
pxe_call = pxenv_call;
if (pxenv_p->Version >= 0x0200) {
for (;;) {
if (bcmp((void *)pxe_p->Signature, S_SIZE("!PXE"))) {
pxe_p = NULL;
break;
}
checksum = 0;
checkptr = (uint8_t *)pxe_p;
for (counter = 0; counter < pxe_p->StructLength;
counter++)
checksum += *checkptr++;
if (checksum != 0) {
pxe_p = NULL;
break;
}
pxe_call = bangpxe_call;
break;
}
}
pxe_p = (pxe_t *)PTOV(pxenv_p->PXEPtr.segment * 16 +
pxenv_p->PXEPtr.offset);
if (bcmp((void *)pxe_p->Signature, S_SIZE("!PXE"))) {
pxe_p = NULL;
return(0);
}
checksum = 0;
checkptr = (uint8_t *)pxe_p;
for (counter = 0; counter < pxe_p->StructLength; counter++)
checksum += *checkptr++;
if (checksum != 0) {
printf("!PXE structure failed checksum. %x\n", checksum);
pxe_p = NULL;
return(0);
}
printf("\n!PXE version %d.%d, real mode entry point @%04x:%04x\n",
(uint8_t) (pxenv_p->Version >> 8),
(uint8_t) (pxenv_p->Version & 0xFF),
pxe_p->EntryPointSP.segment, pxe_p->EntryPointSP.offset);
printf("\nPXE version %d.%d, real mode entry point ",
(uint8_t) (pxenv_p->Version >> 8),
(uint8_t) (pxenv_p->Version & 0xFF));
if (pxe_call == bangpxe_call)
printf("@%04x:%04x\n",
pxe_p->EntryPointSP.segment,
pxe_p->EntryPointSP.offset);
else
printf("@%04x:%04x\n",
pxenv_p->RMEntry.segment, pxenv_p->RMEntry.offset);
gci_p = (t_PXENV_GET_CACHED_INFO *) scratch_buffer;
bzero(gci_p, sizeof(*gci_p));
@ -309,7 +325,7 @@ pxe_close(struct open_file *f)
static void
pxe_print(int verbose)
{
if (pxe_p != NULL) {
if (pxe_call != NULL) {
if (*bootplayer.Sname == '\0') {
printf(" "IP_STR":%s\n",
IP_ARGS(htonl(bootplayer.sip)),
@ -331,17 +347,17 @@ pxe_cleanup(void)
t_PXENV_UNDI_SHUTDOWN *undi_shutdown_p =
(t_PXENV_UNDI_SHUTDOWN *)scratch_buffer;
if (pxe_p == NULL)
if (pxe_call == NULL)
return;
pxe_call(PXENV_UNDI_SHUTDOWN);
if (undi_shutdown_p->Status != 0)
panic("pxe_cleanup: UNDI_SHUTDOWN failed %x",
printf("pxe_cleanup: UNDI_SHUTDOWN failed %x\n",
undi_shutdown_p->Status);
pxe_call(PXENV_UNLOAD_STACK);
if (unload_stack_p->Status != 0)
panic("pxe_cleanup: UNLOAD_STACK failed %x",
printf("pxe_cleanup: UNLOAD_STACK failed %x\n",
unload_stack_p->Status);
}
@ -352,18 +368,46 @@ pxe_perror(int err)
}
void
pxe_call(int func)
pxenv_call(int func)
{
#ifdef PXE_DEBUG
if (debug)
printf("pxenv_call %x\n", func);
#endif
bzero(&v86, sizeof(v86));
bzero(data_buffer, sizeof(data_buffer));
__pxeseg = pxe_p->EntryPointSP.segment;
__pxeoff = pxe_p->EntryPointSP.offset;
__pxenvseg = pxenv_p->RMEntry.segment;
__pxenvoff = pxenv_p->RMEntry.offset;
v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS;
v86.es = VTOPSEG(scratch_buffer);
v86.edi = VTOPOFF(scratch_buffer);
v86.addr = (VTOPSEG(__pxenventry) << 16) | VTOPOFF(__pxenventry);
v86.ebx = func;
v86int();
v86.ctl = V86_FLAGS;
}
void
bangpxe_call(int func)
{
#ifdef PXE_DEBUG
if (debug)
printf("bangpxe_call %x\n", func);
#endif
bzero(&v86, sizeof(v86));
bzero(data_buffer, sizeof(data_buffer));
__bangpxeseg = pxe_p->EntryPointSP.segment;
__bangpxeoff = pxe_p->EntryPointSP.offset;
v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS;
v86.edx = VTOPSEG(scratch_buffer);
v86.eax = VTOPOFF(scratch_buffer);
v86.addr = (VTOPSEG(__h0h0magic) << 16) | VTOPOFF(__h0h0magic);
v86.addr = (VTOPSEG(__bangpxeentry) << 16) | VTOPOFF(__bangpxeentry);
v86.ebx = func;
v86int();
v86.ctl = V86_FLAGS;
@ -390,7 +434,7 @@ pxe_netif_probe(struct netif *nif, void *machdep_hint)
{
t_PXENV_UDP_OPEN *udpopen_p = (t_PXENV_UDP_OPEN *)scratch_buffer;
if (pxe_p == NULL)
if (pxe_call == NULL)
return -1;
bzero(udpopen_p, sizeof(*udpopen_p));

View File

@ -16,16 +16,23 @@
# ph33r this
.globl __h0h0magic, __pxeseg, __pxeoff
.globl __bangpxeentry, __bangpxeseg, __bangpxeoff
.globl __pxenventry, __pxenvseg, __pxenvoff
.code16
.p2align 4,0x90
__h0h0magic:
__bangpxeentry:
push %dx # seg:data
push %ax # off:data
push %bx # int16 func
.byte 0x9a # far call
__pxeoff: .word 0x0000 # offset
__pxeseg: .word 0x0000 # segment
__bangpxeoff: .word 0x0000 # offset
__bangpxeseg: .word 0x0000 # segment
add $6, %sp # restore stack
.byte 0xcb # to vm86int
#
__pxenventry:
.byte 0x9a # far call
__pxenvoff: .word 0x0000 # offset
__pxenvseg: .word 0x0000 # segment
.byte 0xcb # to vm86int