PERFORCE change 118874 for review
Alexey Tarasov
taleks at FreeBSD.org
Fri Apr 27 12:46:51 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=118874
Change 118874 by taleks at 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();
More information about the p4-projects
mailing list