Date: Fri, 27 Apr 2007 12:46:50 GMT From: Alexey Tarasov <taleks@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 118874 for review Message-ID: <200704271246.l3RCkoMJ051651@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=118874 Change 118874 by taleks@taleks_th on 2007/04/27 12:46:48 added code from pxe.c. Now need to find way to install NIC irq handler. Affected files ... .. //depot/projects/soc2007/taleks-pxe_http/pxe_core.c#3 edit .. //depot/projects/soc2007/taleks-pxe_http/pxe_core.h#3 edit Differences ... ==== //depot/projects/soc2007/taleks-pxe_http/pxe_core.c#3 (text+ko) ==== @@ -1,8 +1,38 @@ +#include <stand.h> +#include <string.h> #include "pxe_core.h" #include "pxe_mem.h" #include "pxe_ip.h" #include "pxe_mutex.h" +#include "btxv86.h" +#include "pxe.h" + + +/* PXE API calls here will be made in same way as in pxeboot. + the only difference - installation of isr, that was not needed in pxe.c. + main problem is that, v86 monitors reflects interrupts, + we need to change IDT, for correct irq and call pxe_core_isr() from it. +*/ + +/* NOTE: to think about using of this buffers */ +#define PXE_BUFFER_SIZE 0x2000 +#define PXE_TFTP_BUFFER_SIZE 512 +static char scratch_buffer[PXE_BUFFER_SIZE]; +static char data_buffer[PXE_BUFFER_SIZE]; +static pxenv_t *pxenv_p = NULL; /* PXENV+ */ +static pxe_t *pxe_p = NULL; /* !PXE */ +static BOOTPLAYER bootplayer; /* PXE Cached information. */ + +/* defined in pxetramp.s */ +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); + +/**/ pxe_packet core_packets[PXE_MAX_PACKETS]; pxe_protocol_call core_protocol[256]; pxe_mutex core_mutex={0,0}; @@ -17,20 +47,135 @@ int pxe_core_init() { /* int i=1; /* packet index during initialization loop */ + int counter=0; + uint8_t checksum=0; + uint8_t *checkptr=NULL; + t_PXENV_GET_CACHED_INFO *gci_p=NULL; pxe_memset(core_packets, 0, sizeof(core_packets)); pxe_memset(core_protocol, 0, sizeof(core_protocol)); nic_ip.ip=0; + /* creating 2-linked list of packets */ /* for (; i<PXE_MAX_PACKETS; ++i) { core_packets[i].prev=&core_packets[i-1]; core_packets[i-1].next=&core_packets[i]; } */ + /* 1. determine PXE API entry point */ + + /* + pxe_env is originally is got by pxe_enable() call from + void + pxe_enable(void *pxeinfo) { + pxenv_p = (pxenv_t *)pxeinfo; + pxe_p = (pxe_t *)PTOV(pxenv_p->PXEPtr.segment * 16 + + pxenv_p->PXEPtr.offset); + pxe_call = NULL; + } + in my case, I must decide how to get this. May be it's best way + to use same mechanism. or, if I'll not use BTX code, it'll be + provided other way. So a plenty of things to think. + + */ + if(pxenv_p == NULL) + return (0); + + /* look for "PXENV+" */ + if (bcmp((void *)pxenv_p->Signature, S_SIZE("PXENV+"))) { + pxenv_p = NULL; + return (0); + } + + /* make sure the size is something we can handle */ + if (pxenv_p->Length > sizeof(*pxenv_p)) { + printf("PXENV+ structure too large, ignoring\n"); + pxenv_p = NULL; + return (0); + } + + /* + * do byte checksum: + * add up each byte in the structure, the total should be 0 + */ + checksum = 0; + checkptr = (uint8_t *) pxenv_p; + for (counter = 0; counter < pxenv_p->Length; counter++) + checksum += *checkptr++; + if (checksum != 0) { + printf("PXENV+ structure failed checksum, ignoring\n"); + pxenv_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("\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)); + gci_p->PacketType = PXENV_PACKET_TYPE_BINL_REPLY; + + pxe_core_call(PXENV_GET_CACHED_INFO); + + if (gci_p->Status != 0) { +/* pxe_perror(gci_p->Status);*/ + pxe_p = NULL; + return (0); + } + + bcopy(PTOV((gci_p->Buffer.segment << 4) + gci_p->Buffer.offset), + &bootplayer, gci_p->BufferSize); + + /* 2. install isr */ + pxe_core_install_isr(); + + /* 3. additional start UNDI */ + return 1; } +void pxe_core_install_isr() { +} + +void pxe_core_remove_isr() { +} + int pxe_core_shutdown() { int i=1; @@ -41,9 +186,45 @@ pxe_free(core_packets[i].data); } + /* 1. uninstall isr */ + pxe_core_remove_isr(); + + /* 2. shutdown PXE */ + + 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_core_call(PXENV_UNDI_SHUTDOWN); + pxe_core_call(PXENV_UNLOAD_STACK); + return 1; } +/* + function code is taken from bangpxe_call(), /sys/boot/libi386/pxe.c + needs pxetramp.s wrapper and vm86int() support. + I'll see later , may be it's simplier to do own v86 monitor, + than using provided with BTX. +*/ +void pxe_core_call(int func) { + + 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(__bangpxeentry) << 16) | VTOPOFF(__bangpxeentry); + v86.ebx = func; + v86int(); + v86.ctl = V86_FLAGS; +} + int pxe_core_transmit(pxe_packet* pack) { /* UNDI transmit ip packet call*/ ==== //depot/projects/soc2007/taleks-pxe_http/pxe_core.h#3 (text+ko) ==== @@ -64,6 +64,11 @@ /* interrupt handler function, that used to get new packets */ void pxe_core_isr(); +/* calls PXE/UNDI API, registers of processor must be filled in with + appropriate values. + */ +void pxe_core_call(int func); + /* installs irq handler*/ void pxe_core_install_isr();
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200704271246.l3RCkoMJ051651>