From e938899cc30700c0eefcddf7e168ed50a3904c92 Mon Sep 17 00:00:00 2001 From: Paul Saab Date: Wed, 19 Apr 2000 11:22:38 +0000 Subject: [PATCH] Use !PXE api over PXENV+ api. Magic trampoline by: peter (at 4am and after a good whipping at airhockey) Do a better job of returning and detecting errors. --- sys/boot/i386/libi386/Makefile | 2 +- sys/boot/i386/libi386/pxe.c | 91 ++++++++++++++++++++++++++------ sys/boot/i386/libi386/pxetramp.s | 31 +++++++++++ 3 files changed, 106 insertions(+), 18 deletions(-) create mode 100644 sys/boot/i386/libi386/pxetramp.s diff --git a/sys/boot/i386/libi386/Makefile b/sys/boot/i386/libi386/Makefile index 087c2542fa4b..074fba12636f 100644 --- a/sys/boot/i386/libi386/Makefile +++ b/sys/boot/i386/libi386/Makefile @@ -8,7 +8,7 @@ INTERNALSTATICLIB= true SRCS= aout_freebsd.c biosdisk.c biosmem.c biospnp.c biospci.c \ bootinfo.c comconsole.c devicename.c elf_freebsd.c gatea20.c \ - i386_copy.c i386_module.c time.c vidconsole.c + i386_copy.c i386_module.c time.c vidconsole.c pxetramp.s CFLAGS+= -I${.CURDIR}/../../common -I${.CURDIR}/../btx/lib \ -I${.CURDIR}/../../.. -I. diff --git a/sys/boot/i386/libi386/pxe.c b/sys/boot/i386/libi386/pxe.c index 88a530ded569..a2d56ff09390 100644 --- a/sys/boot/i386/libi386/pxe.c +++ b/sys/boot/i386/libi386/pxe.c @@ -61,7 +61,8 @@ static char scratch_buffer[PXE_BUFFER_SIZE]; static char data_buffer[PXE_BUFFER_SIZE]; -static pxenv_t *pxenv_p = NULL; /* PXENV+ */ +static pxenv_t *pxenv_p = NULL; /* PXENV+ */ +static pxe_t *pxe_p = NULL; /* !PXE */ static BOOTPLAYER bootplayer; /* PXE Cached information. */ static int debug = 0; @@ -77,6 +78,7 @@ static int pxe_strategy(void *devdata, int flag, daddr_t dblk, static int pxe_open(struct open_file *f, ...); static int pxe_close(struct open_file *f); static void pxe_print(int verbose); +static void pxe_cleanup(void); static void pxe_perror(int error); static int pxe_netif_match(struct netif *nif, void *machdep_hint); @@ -89,7 +91,10 @@ 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 char rootpath[FNAME_SIZE]; +extern u_int16_t __pxeseg; +extern u_int16_t __pxeoff; +extern void __h0h0magic(void); struct netif_dif pxe_ifs[] = { /* dif_unit dif_nsel dif_stats dif_private */ @@ -176,10 +181,32 @@ pxe_init(void) pxenv_p = NULL; return (0); } - printf("\nPXENV+ version %d.%d, real mode entry point @%04x:%04x\n", + + 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"))) + 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); + 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), - pxenv_p->RMEntry.segment, pxenv_p->RMEntry.offset); + pxe_p->EntryPointSP.segment, pxe_p->EntryPointSP.offset); gci_p = (t_PXENV_GET_CACHED_INFO *) scratch_buffer; bzero(gci_p, sizeof(*gci_p)); @@ -290,6 +317,23 @@ pxe_print(int verbose) return; } +static void +pxe_cleanup(void) +{ + t_PXENV_UNLOAD_STACK *unload_stack_p = + (t_PXENV_UNLOAD_STACK *)scratch_buffer; + t_PXENV_UNDI_SHUTDOWN *undi_shutdown_p = + (t_PXENV_UNDI_SHUTDOWN *)scratch_buffer; + + pxe_call(PXENV_UNLOAD_STACK); + if (unload_stack_p->Status != 0) + panic("pxe_cleanup: UNLOAD_STACK failed"); + + pxe_call(PXENV_UNDI_SHUTDOWN); + if (undi_shutdown_p->Status != 0) + panic("pxe_cleanup: UNDI_SHUTDOWN failed"); + printf("All cleaned up!\n"); +} void pxe_perror(int err) @@ -302,15 +346,17 @@ pxe_call(int func) { bzero(&v86, sizeof(v86)); bzero(data_buffer, sizeof(data_buffer)); - v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; - /* high 16 == segment, low 16 == offset, shift and or */ - v86.addr = - ((uint32_t)pxenv_p->RMEntry.segment << 16) | pxenv_p->RMEntry.offset; - v86.es = VTOPSEG(scratch_buffer); - v86.edi = VTOPOFF(scratch_buffer); - v86.ebx = func; + + __pxeseg = pxe_p->EntryPointSP.segment; + __pxeoff = 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.ebx = func; v86int(); - v86.ctl = V86_FLAGS; + v86.ctl = V86_FLAGS; } @@ -338,8 +384,10 @@ pxe_netif_probe(struct netif *nif, void *machdep_hint) udpopen_p->src_ip = bootplayer.yip; pxe_call(PXENV_UDP_OPEN); - if (udpopen_p->status != 0) + if (udpopen_p->status != 0) { printf("pxe_netif_probe: failed %x\n", udpopen_p->status); + return -1; + } return 0; } @@ -386,11 +434,14 @@ sendudp(struct iodesc *h, void *pkt, size_t len) pxe_call(PXENV_UDP_WRITE); +#if 0 /* XXX - I dont know why we need this. */ delay(1000); - if (udpwrite_p->status != 0) +#endif + if (udpwrite_p->status != 0) { printf("sendudp failed %x\n", udpwrite_p->status); - + return -1; + } return len; } @@ -411,10 +462,16 @@ readudp(struct iodesc *h, void *pkt, size_t len, time_t timeout) pxe_call(PXENV_UDP_READ); +#if 0 /* XXX - I dont know why we need this. */ delay(1000); - if (udpread_p->status > 1) - printf("readudp failed %x\n", udpread_p->status); +#endif + if (udpread_p->status != 0) { + /* XXX: This happens a lot. It shouldn't. */ + if (udpread_p->status != 1) + printf("readudp failed %x\n", udpread_p->status); + return -1; + } bcopy(data_buffer, pkt, udpread_p->buffer_size); uh->uh_sport = udpread_p->s_port; return udpread_p->buffer_size; diff --git a/sys/boot/i386/libi386/pxetramp.s b/sys/boot/i386/libi386/pxetramp.s new file mode 100644 index 000000000000..7fda5028944a --- /dev/null +++ b/sys/boot/i386/libi386/pxetramp.s @@ -0,0 +1,31 @@ +# +# Copyright (c) 2000 Peter Wemm +# All rights reserved. +# +# Redistribution and use in source and binary forms are freely +# permitted provided that the above copyright notice and this +# paragraph and the following disclaimer are duplicated in all +# such forms. +# +# This software is provided "AS IS" and without any express or +# implied warranties, including, without limitation, the implied +# warranties of merchantability and fitness for a particular +# purpose. +# +# $FreeBSD$ + +# ph33r this + + .globl __h0h0magic, __pxeseg, __pxeoff + + .code16 + .p2align 4,0x90 +__h0h0magic: + push %dx # seg:data + push %ax # off:data + push %bx # int16 func + .byte 0x9a # far call +__pxeoff: .word 0x0000 # offset +__pxeseg: .word 0x0000 # segment + add $6, %sp # restore stack + .byte 0xcb # to vm86int