summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorps <ps@FreeBSD.org>2000-04-26 07:38:40 +0000
committerps <ps@FreeBSD.org>2000-04-26 07:38:40 +0000
commitfbbbd9977455918c349a1fbdff28e8d3c1ca6975 (patch)
tree78f83c609ae974d3ebf0628dea7a1df97b47b39e
parentb7ff0a8cb072b72d9fb97bba88d1a34ba9f4a71b (diff)
downloadFreeBSD-src-fbbbd9977455918c349a1fbdff28e8d3c1ca6975.zip
FreeBSD-src-fbbbd9977455918c349a1fbdff28e8d3c1ca6975.tar.gz
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.
-rw-r--r--sys/boot/i386/libi386/pxe.c126
-rw-r--r--sys/boot/i386/libi386/pxetramp.s15
2 files changed, 96 insertions, 45 deletions
diff --git a/sys/boot/i386/libi386/pxe.c b/sys/boot/i386/libi386/pxe.c
index 27c8608..101e555 100644
--- a/sys/boot/i386/libi386/pxe.c
+++ b/sys/boot/i386/libi386/pxe.c
@@ -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);
- }
-
- 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);
+
+ /*
+ * 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;
+ }
}
-
-
- 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));
+
+ __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));
- __pxeseg = pxe_p->EntryPointSP.segment;
- __pxeoff = pxe_p->EntryPointSP.offset;
+ __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));
diff --git a/sys/boot/i386/libi386/pxetramp.s b/sys/boot/i386/libi386/pxetramp.s
index 7fda502..a797e73 100644
--- a/sys/boot/i386/libi386/pxetramp.s
+++ b/sys/boot/i386/libi386/pxetramp.s
@@ -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
OpenPOWER on IntegriCloud