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:
parent
d56a3c0de0
commit
7fbc9ae671
@ -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));
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user