git: 9front

Download patch

ref: 438383b2ec098fb86af9d13f1e40cc6c212a8353
parent: c7f7f5bbdf7360e20a5a93a613964f9ea3926ca4
author: cinap_lenrek <cinap_lenrek@localhost>
date: Wed Apr 20 06:49:54 EDT 2011

9boot: pxe/kernel memory overlap problem, add unload function

--- a/sys/src/boot/pc/a20.s
+++ b/sys/src/boot/pc/a20.s
@@ -4,16 +4,14 @@
 
 TEXT a20(SB), $0
 	CALL rmode16(SB)
-	STI
+	CALL16(spllo(SB))
 	LWI(0x2401, rAX)
 	BIOSCALL(0x15)
 	JC _biosfail
-	CLI
 	CALL16(pmode32(SB))
 	RET
 
 _biosfail:
-	CLI
 	CALL16(pmode32(SB))
 
 	CALL a20wait(SB)
--- a/sys/src/boot/pc/fat.c
+++ b/sys/src/boot/pc/fat.c
@@ -63,6 +63,11 @@
 
 int readsect(ulong drive, ulong lba, void *buf);
 
+void
+unload(void)
+{
+}
+
 int
 read(void *f, void *data, int len)
 {
--- a/sys/src/boot/pc/fns.h
+++ b/sys/src/boot/pc/fns.h
@@ -16,6 +16,7 @@
 int read(void *f, void *data, int len);
 int readn(void *f, void *data, int len);
 void close(void *f);
+void unload(void);
 
 void memset(void *p, int v, int n);
 void memmove(void *dst, void *src, int n);
--- a/sys/src/boot/pc/iso.c
+++ b/sys/src/boot/pc/iso.c
@@ -39,6 +39,11 @@
 
 int readsect(ulong drive, ulong lba, void *buf);
 
+void
+unload(void)
+{
+}
+
 int
 read(void *f, void *data, int len)
 {
--- a/sys/src/boot/pc/l.s
+++ b/sys/src/boot/pc/l.s
@@ -79,9 +79,6 @@
 	JMP _segret
 
 TEXT rmode16x(SB), $0
-	/* reload idt */
-	SEGSS; LIDT(tidtptr(SB))
-
 	/* disable protected mode */
 	MFCR(rCR0, rCX)
 	ANDB $0xfe, CL
@@ -124,10 +121,6 @@
          WORD $(5*8) 
          LONG $tgdt(SB)
 
-TEXT tidtptr(SB), $0
-	WORD $0x3ff
-	LONG $0
-
 TEXT jump(SB), $0
 	MOVL 4(SP), AX
 	JMP *AX
@@ -180,6 +173,33 @@
 
 #ifdef PXE
 
+TEXT pxeinit(SB), $0
+	CALL rmode16(SB)
+
+	/* get pxe env structure in ES:BX */
+	LWI(0x5650, rAX)
+	BIOSCALL(0x1A)
+	JC _pret32
+
+	/* !PXE or PXEENV+ signature */
+	SEGES; LXW(0, xBX, rAX)
+	CMPI((('!'<<0)|('P'<<8)), rAX)
+	JEQ _getentry
+	CMPI((('P'<<0)|('X'<<8)), rAX)
+	JNE _pret32
+
+	SEGES; LXW(0x2A, xBX, rAX)
+	SEGES; LXW(0x28, xBX, rBX)
+	MTSR(rAX, rES)
+
+_getentry:
+	SEGES; LXW(0x12, xBX, rAX)
+	SW(rAX, pxepseg(SB))
+	SEGES; LXW(0x10, xBX, rAX)
+	SW(rAX, pxepoff(SB))
+	CLR(rAX)
+	JMP _pret32
+
 TEXT pxecallret(SB), $0
 	ADDI(6, rSP)
 	JMP _pret32
@@ -200,26 +220,9 @@
 	PUSHR(rCX)
 	PUSHI(pxecallret(SB))
 
-	/* get pxe env structure in ES:BX */
-	LWI(0x5650, rAX)
-	BIOSCALL(0x1A)
-	JC _farret
-
-	/* !PXE or PXEENV+ signature */
-	SEGES; LXW(0, xBX, rAX)
-	CMPI((('!'<<0)|('P'<<8)), rAX)
-	JEQ _getentry
-	CMPI((('P'<<0)|('X'<<8)), rAX)
-	JNE _farret
-
-	SEGES; LXW(0x2A, xBX, rAX)
-	SEGES; LXW(0x28, xBX, rBX)
-	MTSR(rAX, rES)
-
-_getentry:
-	SEGES; LXW(0x12, xBX, rAX)
+	LW(pxepseg(SB), rAX)
 	PUSHR(rAX)
-	SEGES; LXW(0x10, xBX, rAX)
+	LW(pxepoff(SB), rAX)
 	PUSHR(rAX)
 
 	CALL16(spllo(SB))
@@ -230,8 +233,12 @@
 	CLR(rDX)
 	CLR(rDI)
 	CLR(rSI)
-_farret:
 	FARRET
+
+TEXT pxepseg(SB), $0
+	WORD $0
+TEXT pxepoff(SB), $0
+	WORD $0
 
 #else /* PXE */
 
--- a/sys/src/boot/pc/mem.h
+++ b/sys/src/boot/pc/mem.h
@@ -13,62 +13,17 @@
 #define	PGSHIFT		12			/* log(BY2PG) */
 #define	PGROUND(s)	(((s)+(BY2PG-1))&~(BY2PG-1))
 
-#define	MAXMACH		1			/* max # cpus system can run */
-
 /*
- * Time
- */
-#define	HZ		(100)				/* clock frequency */
-#define	MS2HZ		(1000/HZ)			/* millisec per clock tick */
-#define	TK2SEC(t)	((t)/HZ)			/* ticks to seconds */
-#define	TK2MS(x)	((x)*(1000/HZ))
-#define	MS2TK(t)	((((ulong)(t))*HZ)/1000)	/* milliseconds to ticks */
-
-/*
  * Fundamental addresses
  */
-#define IDTADDR		0x80000800		/* idt */
-#define APBOOTSTRAP	0x80001000		/* AP bootstrap code */
 #define CONFADDR	0x80001200		/* info passed from boot loader */
-#define CPU0PDB		0x80002000		/* bootstrap processor PDB */
-#define CPU0PTE		0x80003000		/* bootstrap processor PTE's for 0-4MB */
-#define MACHADDR	0x80004000		/* as seen by current processor */
-#define CPU0MACH	0x80005000		/* Mach for bootstrap processor */
 #define BIOSXCHG	0x80006000		/* To exchange data with the BIOS */
-#define	MACHSIZE	(BY2PG*8)		/* stack size */
 
-/*
- *  Address spaces
- *
- *  Kernel is at 2GB-4GB
- */
-#define	KZERO		0x80000000		/* base of kernel address space */
-#define	KTZERO		KZERO			/* first address in kernel text */
-#define ROMBIOS		(KZERO|0xF0000)
-
-/*
- *  known 80386 segments (in GDT) and their selectors
- */
-#define	NULLSEG	0	/* null segment */
-#define	KDSEG	1	/* kernel data/stack */
-#define	KESEG	2	/* kernel executable */	
-#define	UDSEG	3	/* user data/stack */
-#define	UESEG	4	/* user executable */
-#define	SYSGATE	5	/* system call gate */
-#define TSSSEG	6	/* task segment */
-
 #define SELGDT	(0<<3)	/* selector is in gdt */
 #define	SELLDT	(1<<3)	/* selector is in ldt */
 
 #define SELECTOR(i, t, p)	(((i)<<3) | (t) | (p))
 
-#define NULLSEL	SELECTOR(NULLSEG, SELGDT, 0)
-#define KESEL	SELECTOR(KESEG, SELGDT, 0)
-#define KDSEL	SELECTOR(KDSEG, SELGDT, 0)
-#define UESEL	SELECTOR(UESEG, SELGDT, 3)
-#define UDSEL	SELECTOR(UDSEG, SELGDT, 3)
-#define TSSSEL	SELECTOR(TSSSEG, SELGDT, 0)
-
 /*
  *  fields in segment descriptors
  */
@@ -89,26 +44,3 @@
 #define	SEGR	(1<<9)		/* readable (for code) */
 #define SEGD	(1<<22)		/* default 1==32bit (for code) */
 
-/*
- *  virtual MMU
- */
-#define PTEMAPMEM	(1024*1024)	/* ??? */	
-#define SEGMAPSIZE	16		/* ??? */
-#define	PTEPERTAB	(PTEMAPMEM/BY2PG)	/* ??? */
-#define PPN(x)		((x)&~(BY2PG-1))
-
-/*
- *  physical MMU
- */
-#define	PTEVALID	(1<<0)
-#define	PTEUNCACHED	0		/* everything is uncached */
-#define	PTEWRITE	(1<<1)
-#define	PTERONLY	(0<<1)
-#define	PTEKERNEL	(0<<2)
-#define	PTEUSER		(1<<2)
-#define	PTESIZE		(1<<7)
-
-/*
- *  flag register bits that we care about
- */
-#define IFLAG	0x200
--- a/sys/src/boot/pc/pxe.c
+++ b/sys/src/boot/pc/pxe.c
@@ -57,6 +57,7 @@
 	char bootfile[128];
 };
 
+int pxeinit(void);
 int pxecall(int op, void *buf);
 
 static void*
@@ -105,6 +106,17 @@
 	memmove(d, s, sizeof(d));
 }
 
+void
+unload(void)
+{
+	struct {
+		uchar status[2];
+		uchar junk[10];
+	} buf;
+	puts(buf.status, 0);
+	pxecall(0x70, &buf);
+}
+
 static int
 getip(IP4 yip, IP4 sip, IP4 gip, char mac[16])
 {
@@ -153,7 +165,7 @@
 static int
 udpclose(void)
 {
-	char status[2];
+	uchar status[2];
 	puts(status, 0);
 	return pxecall(0x31, status);
 }
@@ -268,6 +280,7 @@
 	udpclose();
 }
 
+
 static int
 tftpopen(Tftp *t, char *path, IP4 sip, IP4 dip, IP4 gip)
 {
@@ -311,6 +324,10 @@
 	void *f;
 	Tftp t;
 
+	if(pxeinit()){
+		print("pxe init\r\n");
+		halt();
+	}
 	if(getip(yip, sip, gip, mac)){
 		print("bad dhcp\r\n");
 		halt();
--- a/sys/src/boot/pc/sub.c
+++ b/sys/src/boot/pc/sub.c
@@ -18,9 +18,18 @@
 {
 	uchar *d = dst;
 	uchar *s = src;
-	while(n > 0){
-		*d++ = *s++;
-		n--;
+	if(d < s){
+		while(n > 0){
+			*d++ = *s++;
+			n--;
+		}
+	} if(d > s){
+		s += n;
+		d += n;
+		while(n > 0){
+			*--d = *--s;
+			n--;
+		}
 	}
 }
 
@@ -192,9 +201,9 @@
 char*
 bootkern(void *f)
 {
-	uchar *e, *d;
+	uchar *e, *d, *t;
+	ulong n;
 	Exec ex;
-	int n;
 
 	a20();
 	if(readn(f, &ex, sizeof(ex)) != sizeof(ex))
@@ -202,14 +211,25 @@
 	if(beswal(ex.magic) != I_MAGIC)
 		return "bad magic";
 	e = (uchar*)(beswal(ex.entry) & ~0xF0000000UL);
+
+	/*
+	 * the kernels load addess (entry) might overlap
+	 * with some bios memory (pxe) that is needed to load
+	 * it. so we read it to this address and after
+	 * we finished, move it to final location.
+	 */
+	t = (uchar*)0x200000;
 	n = beswal(ex.text);
-	if(readn(f, e, n) != n)
+	if(readn(f, t, n) != n)
 		goto Error;
-	d = (uchar*)(((ulong)e + n + 0xFFF) & ~0xFFFUL);
+	d = t + ((uchar*)PGROUND((ulong)e + n) - e);
 	n = beswal(ex.data);
 	if(readn(f, d, n) != n)
 		goto Error;
 	close(f);
+	unload();
+	n = (d + n) - t;
+	memmove(e, t, n);
 	jump(e);
 Error:		
 	return "i/o error";
--