Subject: port-i386/3336: dosboot.com doesn't work with Windows 95 default installation
To: None <gnats-bugs@gnats.netbsd.org>
From: None <martin@rumolt.teuto.de>
List: netbsd-bugs
Date: 03/16/1997 05:05:13
>Number: 3336
>Category: port-i386
>Synopsis: dosboot.com doesn't work with Windows 95 default installation
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: gnats-admin (GNATS administrator)
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Sat Mar 15 20:20:02 1997
>Last-Modified:
>Originator: Martin Husemann
>Organization:
private
>Release: Mar 15
>Environment:
System: NetBSD rumolt.teuto.de 1.2C NetBSD 1.2C (RUMOLT) #2: Sat Mar 15 11:35:35 MET 1997 root@rumolt.teuto.de:/usr/src/sys-isdn/arch/i386/compile/RUMOLT i386
>Description:
The new (experimental) dosboot.com utilitiy from
src/sys/arch/i386/stand/dosboot doesn't work with any reasonable nowadays DOS
installation. If any memory manager is installed (himem.sys will do) it won't
see any extended memory and will crash DOS before having done all its
DOS-based IO.
>How-To-Repeat:
Walk to a Windows 95 system nearby, hit F8, 6, ENTER on boot and try
dosboot.com.
>Fix:
Apply the following fix (or something similar). This adds XMS support
and double-buffers the loaded kernel before crashing DOS. Works for me,
although it might fail if the stringtable in the kernel is bigger than
64k. Probably the right way to handle this is to allocate a second
temporary XMS buffer when the stringtable size is known, but it's too
late now for me. The assembler doesn't handle some constructs correct
when in 16/8 bit mode, so be carefull (and disassemble afterwards) if
changing the assembler code!
Small bug: this gets the extended memory size a few k to small (XMS
doesn't count the UMB as extended memory), but it's only a few k and
I didn't bother finding out how much exactly it is. Probably rounding up
to the next MB boundary would do...
diff -rc5 sys/arch/i386/stand.orig/lib/biosmem.S sys/arch/i386/stand/lib/biosmem.S
*** sys/arch/i386/stand.orig/lib/biosmem.S Fri Mar 14 13:52:07 1997
--- sys/arch/i386/stand/lib/biosmem.S Sun Mar 16 04:37:15 1997
***************
*** 37,47 ****
#define data32 .byte 0x66
.text
! /* get mem above 1M, in kByte */
ENTRY(getbasemem)
pushl %ebp
movl %esp,%ebp
pushl %ebx
--- 37,47 ----
#define data32 .byte 0x66
.text
! /* get mem below 1M, in kByte */
ENTRY(getbasemem)
pushl %ebp
movl %esp,%ebp
pushl %ebx
***************
*** 64,73 ****
--- 64,79 ----
pop %esi
popl %ebx
popl %ebp
ret
+ /* global pointer to XMS driver, 0 if no XMS used */
+
+ .globl _xmsdrv
+ _xmsdrv:
+ .long 0
+
/* get mem above 1M, in kByte */
ENTRY(getextmem)
pushl %ebp
movl %esp,%ebp
***************
*** 77,86 ****
--- 83,127 ----
call _C_LABEL(prot_to_real)
movb $0x88,%ah
int $0x15
+
+ testw %ax, %ax/* test for extended memory = 0, this may happen */
+ jnz xdone /* if himem.sys is installed and grabed all available */
+ /* memory. */
+ /* determine memory size by calling XMS then... */
+
+ .byte 0xb8 /* movw $0x4300,ax */
+ .word 0x4300
+ int $0x2f /* check if XMS installed */
+ cmpb $0x80, %al
+ jnz noxms
+
+ .byte 0xb8 /* movw $0x4310,ax */
+ .word 0x4310
+ int $0x2f /* get driver address */
+
+ .byte 0x89,0x1e /* save es:bx to _xmsdrv */
+ .word _xmsdrv
+ .byte 0x8c,0x06
+ .word _xmsdrv+2
+
+ movb $0x08, %ah /* XMS: query free extended memory */
+ movb $0x00, %bl
+ .byte 0xff, 0x1e
+ .word _xmsdrv
+
+ data32
+ movw %dx, %ax
+ jmp xdone
+
+ noxms: /* no XMS manager found */
+ data32 /* revert to former result (no extended memory) */
+ movl $0, %eax
+
+ xdone:
data32
movl $0, %ebx
mov %ax,%bx
data32
***************
*** 89,96 ****
--- 130,208 ----
movl %ebx, %eax
pop %edi
pop %esi
popl %ebx
+ popl %ebp
+ ret
+
+ /*
+ Allocate a block of XMS memory with the requested size
+ void * xmsalloc(long int kBytes);
+
+ Depends on _xmsdrv being set by getextmem() before first call
+ to this function.
+
+ Return value: a physical address.
+ */
+ ENTRY(xmsalloc)
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+
+ movl 0x8(%ebp), %edx # Kbytes needed
+
+ call _C_LABEL(prot_to_real) # enter real mode
+
+ movb $0x09, %ah # XMS allocate block
+ .byte 0xff,0x1e
+ .word _xmsdrv # result: handle in %dx
+ movb $0x0c, %ah # XMS lock block
+ .byte 0xff,0x1e
+ .word _xmsdrv # result: 32 bit physical address in DX:BX
+
+ data32
+ call _C_LABEL(real_to_prot) # back to protected mode
+
+ movl %edx, %eax
+ shl $16, %eax
+ movw %bx, %ax # result in %eax
+
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+
+ /*
+ * ppbcopy(src, dst, cnt)
+ * where src and dst are physical addresses
+ */
+ ENTRY(ppbcopy)
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %es
+ pushl %esi
+ pushl %edi
+
+ cld
+
+ # set %es to point at the flat segment
+ movl $flatdataseg, %eax
+ movl %ax, %es
+
+ movl 8(%ebp), %esi # source
+ movl 12(%ebp), %edi # destination
+ movl 16(%ebp), %ecx # count
+
+ es
+ rep
+ movsb
+
+ popl %edi
+ popl %esi
+ popl %es
popl %ebp
ret
diff -rc5 sys/arch/i386/stand.orig/lib/exec.c sys/arch/i386/stand/lib/exec.c
*** sys/arch/i386/stand.orig/lib/exec.c Fri Mar 14 13:52:13 1997
--- sys/arch/i386/stand/lib/exec.c Sun Mar 16 04:36:06 1997
***************
*** 82,91 ****
--- 82,94 ----
struct exec x;
int cc, magic;
physaddr_t entry;
register physaddr_t cp;
u_long boot_argv[6];
+ long kernsize = 0;
+ physaddr_t tmpbuf = 0;
+ long origadr;
#ifdef COMPAT_OLDBOOT
char *fsname, *devname;
int unit, part;
const char *filename;
***************
*** 120,129 ****
--- 123,141 ----
if(!loadaddr) loadaddr = (entry & 0x100000);
cp = loadaddr;
+ if (xmsdrv) {
+ /* Determine size of temporary buffer. Reserve some extra space for string table,
+ * konvert to kB by rounding up. */
+ kernsize = (x.a_text + x.a_data + x.a_bss + sizeof(x.a_syms) + x.a_syms + 64*1024 + 1023) / 1024;
+ tmpbuf = xmsalloc(kernsize);
+ origadr = cp;
+ cp = tmpbuf;
+ }
+
/*
* Leave a copy of the exec header before the text.
* The kernel may use this to verify that the
* symbols were loaded by this boot program.
*/
***************
*** 193,203 ****
goto shread;
cp += cc;
}
boot_argv[3] = (((u_int)cp + sizeof(int) - 1)) & (-sizeof(int));
! printf("=0x%lx\n", cp - loadaddr);
boot_argv[0] = boothowto;
#ifdef COMPAT_OLDBOOT
/* prepare boot device information for kernel */
--- 205,218 ----
goto shread;
cp += cc;
}
boot_argv[3] = (((u_int)cp + sizeof(int) - 1)) & (-sizeof(int));
! if (tmpbuf)
! printf("=0x%lx\n", cp - tmpbuf);
! else
! printf("=0x%lx\n", cp - loadaddr);
boot_argv[0] = boothowto;
#ifdef COMPAT_OLDBOOT
/* prepare boot device information for kernel */
***************
*** 240,249 ****
--- 255,273 ----
close(io);
#ifdef DEBUG
printf("Start @ 0x%lx ...\n", entry);
#endif
+
+ if (xmsdrv) {
+ /*
+ * We know have done our last DOS IO, so we may
+ * trash the OS. Copy the data from the temporary
+ * buffer to its real adress.
+ */
+ ppbcopy(tmpbuf, origadr, kernsize * 1024);
+ }
startprog(entry, 6, boot_argv, 0x90000);
panic("exec returned");
shread:
diff -rc5 sys/arch/i386/stand.orig/lib/libi386.h sys/arch/i386/stand/lib/libi386.h
*** sys/arch/i386/stand.orig/lib/libi386.h Fri Mar 14 13:52:15 1997
--- sys/arch/i386/stand/lib/libi386.h Sun Mar 16 04:35:27 1997
***************
*** 38,47 ****
--- 38,51 ----
void vpbcopy __P((void*, physaddr_t, int));
void pvbcopy __P((physaddr_t, void*, int));
void pbzero __P((physaddr_t, int));
physaddr_t vtophys __P((void*));
+ extern int xmsdrv;
+ physaddr_t ppbcopy __P((physaddr_t, physaddr_t, int));
+ physaddr_t xmsalloc __P((int));
+
int pread __P((int, physaddr_t, int));
void startprog __P((physaddr_t, int, unsigned long*, physaddr_t));
int exec_netbsd __P((const char*, physaddr_t, int, char*, char*));
int netbsd_opt __P((char));
>Audit-Trail:
>Unformatted: