Skip site navigation (1)Skip section navigation (2)
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>