diff options
-rw-r--r-- | sys/arch/i386/boot/asm.S | 16 | ||||
-rw-r--r-- | sys/arch/i386/boot/bios.S | 131 | ||||
-rw-r--r-- | sys/arch/i386/boot/boot.c | 42 | ||||
-rw-r--r-- | sys/arch/i386/boot/disk.c | 29 | ||||
-rw-r--r-- | sys/arch/i386/boot/io.c | 40 | ||||
-rw-r--r-- | sys/arch/i386/boot/start.S | 7 | ||||
-rw-r--r-- | sys/arch/i386/boot/sys.c | 31 | ||||
-rw-r--r-- | sys/arch/i386/boot/version.c | 7 |
8 files changed, 279 insertions, 24 deletions
diff --git a/sys/arch/i386/boot/asm.S b/sys/arch/i386/boot/asm.S index 18261ffad28..5d9f708eef5 100644 --- a/sys/arch/i386/boot/asm.S +++ b/sys/arch/i386/boot/asm.S @@ -103,10 +103,13 @@ xprot: */ ENTRY(prot_to_real) # set up a dummy stack frame for the second seg change. - movl _ourseg, %eax - pushw %ax - movl $xreal, %eax # gas botches pushw $xreal - extra bytes 0, 0 - pushw %ax # decode to add %al, (%eax) (%al usually 0) + # Adjust the intersegment jump instruction following + # the clearing of protected mode bit. + # This is self-modifying code, but we need a writable + # code segment, and an intersegment return does not give us that. + movl _ourseg, %eax + movw %ax, xreal-2 + # Change to use16 mode. ljmp $0x28, $x16 @@ -121,7 +124,10 @@ x16: # make intersegment jmp to flush the processor pipeline # using the fake stack frame set up earlier # and reload CS register - lret + # Here we have an 16 bits intersegment jump. + .byte 0xea + .word xreal + .word 0 xreal: # we are in real mode now diff --git a/sys/arch/i386/boot/bios.S b/sys/arch/i386/boot/bios.S index ea00644b7fa..b6f79b5e5eb 100644 --- a/sys/arch/i386/boot/bios.S +++ b/sys/arch/i386/boot/bios.S @@ -71,6 +71,8 @@ ENTRY(biosread) pushl %ebp movl %esp, %ebp pushl %ebx + pushl %esi + pushl %edi movb 16(%ebp), %dh movw 12(%ebp), %cx @@ -97,11 +99,120 @@ ENTRY(biosread) xorl %eax, %eax movb %bl, %al # return value in %ax + popl %edi + popl %esi popl %ebx popl %ebp ret +#ifdef DOSREAD +/* +# MSDOS call "INT 0x21 Function 0x3d" to open a file. +# Call with %ah = 0x3d +# %al = 0x0 (access and sharing modes) +# %ds:%dx = ASCIZ filename +# %cl = attribute mask of files to look for +*/ +ENTRY(dosexit) + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %esi + pushl %edi + movl 0x8(%ebp), %ebx # exit code + call _C_LABEL(prot_to_real) # enter real mode + movb %bl, %al # exit code + movb $0x4c , %ah # Exit + int $0x21 + cli + hlt + +ENTRY(dosopen) + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %esi + pushl %edi + movl 0x8(%ebp), %edx # File name. + movb $0x0 , %cl # Attribute mask. + call _C_LABEL(prot_to_real) # enter real mode + movb $0x3d, %ah # Open existing file. + movb $0x0 , %al # Compatibility mode + int $0x21 + jnc ok1 + addr32 + movl %eax, _C_LABEL(doserrno) + data32 + movl $-1, %eax +ok1: + pushl %eax + data32 + call _C_LABEL(real_to_prot) # back to protected mode + xorl %eax, %eax + popw %ax # return value in %eax + popl %edi + popl %esi + popl %ebx + popl %ebp + ret +ENTRY(dosread) + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %esi + pushl %edi + movl 0x8(%ebp), %ebx # File handle + movl 0xc(%ebp), %edx # Buffer. + movl 0x10(%ebp) , %ecx # Bytes to read + call _C_LABEL(prot_to_real) # enter real mode + movb $0x3f, %ah # Read from file or device + movb $0x0 , %al # Compatibility mode + int $0x21 + jnc ok2 + addr32 + movl %eax, _C_LABEL(doserrno) + data32 + movl $-1, %eax +ok2: + pushl %eax + data32 + call _C_LABEL(real_to_prot) # back to protected mode + xorl %eax, %eax + popw %ax # return value in %eax + popl %edi + popl %esi + popl %ebx + popl %ebp + ret +ENTRY(dosclose) + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %esi + pushl %edi + movl 0x8(%ebp), %ebx # File handle + call _C_LABEL(prot_to_real) # enter real mode + movb $0x3e, %ah # Close file. + movb $0x0 , %al # Compatibility mode + int $0x21 + jnc ok3 + addr32 + movl %eax, _C_LABEL(doserrno) + data32 + movl $-1, %eax +ok3: + pushl %eax + data32 + call _C_LABEL(real_to_prot) # back to protected mode + xorl %eax, %eax + popw %ax # return value in %eax + popl %edi + popl %esi + popl %ebx + popl %ebp + ret +#endif /* #ifndef SERIAL # BIOS call "INT 10H Function 0Eh" to write character to console @@ -120,6 +231,8 @@ ENTRY(putc) pushl %ebp movl %esp, %ebp pushl %ebx + pushl %esi + pushl %edi movb 8(%ebp), %cl @@ -141,6 +254,8 @@ ENTRY(putc) data32 call _C_LABEL(real_to_prot) + popl %edi + popl %esi popl %ebx popl %ebp ret @@ -164,6 +279,8 @@ ENTRY(getc) pushl %ebp movl %esp, %ebp pushl %ebx + pushl %esi + pushl %edi call _C_LABEL(prot_to_real) @@ -184,6 +301,8 @@ ENTRY(getc) xorl %eax, %eax movb %bl, %al + popl %edi + popl %esi popl %ebx popl %ebp ret @@ -212,6 +331,8 @@ ENTRY(ischar) pushl %ebp movl %esp, %ebp pushl %ebx + pushl %esi + pushl %edi call _C_LABEL(prot_to_real) @@ -234,6 +355,8 @@ ENTRY(ischar) xorl %eax, %eax movb %bl, %al + popl %edi + popl %esi popl %ebx popl %ebp ret @@ -249,6 +372,8 @@ ENTRY(get_diskinfo) pushl %ebp movl %esp, %ebp pushl %ebx + pushl %esi + pushl %edi movb 8(%ebp), %dl # diskinfo(drive #) @@ -284,6 +409,8 @@ ok: andb $0x3f, %cl # mask of cylinder gunk movb %cl, %al # max sector (and # sectors) + popl %edi + popl %esi popl %ebx popl %ebp ret @@ -302,6 +429,8 @@ ENTRY(memsize) pushl %ebp movl %esp, %ebp pushl %ebx + pushl %esi + pushl %edi movl 8(%ebp), %ebx @@ -326,6 +455,8 @@ xdone: call _C_LABEL(real_to_prot) movl %ebx, %eax + popl %edi + popl %esi popl %ebx popl %ebp ret diff --git a/sys/arch/i386/boot/boot.c b/sys/arch/i386/boot/boot.c index 0e55dbdf62d..86c7adbb448 100644 --- a/sys/arch/i386/boot/boot.c +++ b/sys/arch/i386/boot/boot.c @@ -73,7 +73,7 @@ char *names[] = { static void getbootdev __P((int *howto)); static void loadprog __P((int howto)); -extern char *version; +extern char version[]; extern int end; void @@ -85,6 +85,7 @@ boot(drive) printf("\n" ">> OpenBSD BOOT: %d/%d k [%s]\n" + "use ? for file list, or carriage return for defaults\n" "use hd(1,a)/bsd to boot sd0 when wd0 is also installed\n", argv[7] = memsize(0), argv[8] = memsize(1), @@ -95,21 +96,36 @@ loadstart: * As a default set it to the first partition of the first * * floppy or hard drive * \***************************************************************/ - part = 0; - unit = drive&0x7f; - maj = (drive&0x80 ? 0 : 2); /* a good first bet */ +#ifdef DOSREAD + if (drive== 0xff) { + maj = 5; + part = 0; + unit = 0; + } else +#endif + { + part = 0; + unit = drive&0x7f; + maj = (drive&0x80 ? 0 : 2); /* a good first bet */ + } name = names[currname++]; loadflags = 0; - if (currname == NUMNAMES) - currname = 0; getbootdev(&loadflags); - if (openrd()) { + switch(openrd()) { + case 0: + loadprog(loadflags); + break; + case -1: + currname--; + break; + default: printf("Can't find %s\n", name); - goto loadstart; + break; } - loadprog(loadflags); + if (currname == NUMNAMES) + currname = 0; goto loadstart; } @@ -128,8 +144,6 @@ loadprog(howto) return; } - poff = N_TXTOFF(head); - startaddr = (int)head.a_entry; addr = (startaddr & 0x00f00000); /* some MEG boundary */ printf("Booting %s(%d,%c)%s @ 0x%x\n", @@ -149,7 +163,8 @@ loadprog(howto) /* LOAD THE TEXT SEGMENT */ /********************************************************/ printf("%d", head.a_text); - xread(addr, head.a_text); + pcpy(&head, addr, sizeof(head)); + xread(addr+sizeof(head), head.a_text - sizeof(head)); #ifdef CHECKSUM if (cflag) printf("(%x)", cksum(addr, head.a_text)); @@ -223,6 +238,9 @@ loadprog(howto) } putchar(']'); +#ifdef DOSREAD + doclose(); +#endif /********************************************************/ /* and that many bytes of (debug symbols?) */ diff --git a/sys/arch/i386/boot/disk.c b/sys/arch/i386/boot/disk.c index 0f37b2471d1..4bf990cca7c 100644 --- a/sys/arch/i386/boot/disk.c +++ b/sys/arch/i386/boot/disk.c @@ -41,7 +41,11 @@ #define SPT(di) ((di)&0xff) #define HEADS(di) ((((di)>>8)&0xff)+1) +#ifdef DOSREAD +char *devs[] = {"wd", "hd", "fd", "wt", "sd", "dos", 0}; +#else char *devs[] = {"wd", "hd", "fd", "wt", "sd", 0}; +#endif #ifdef DO_BAD144 struct dkbad dkb; @@ -148,11 +152,28 @@ static char ra_buf[RA_SECTORS * BPS]; static int ra_dev; static int ra_end; static int ra_first; +static int ra_sectors; +static int ra_skip; Bread(sector, addr) int sector; void *addr; { + extern int ourseg; + int dmalimit = ((((ourseg<<4)+(int)ra_buf)+65536) & ~65535) + - ((ourseg<<4)+ (int)ra_buf); + if (dmalimit<RA_SECTORS*BPS) { + if (dmalimit*2<RA_SECTORS*BPS) { + ra_sectors = (RA_SECTORS*BPS-dmalimit)/BPS; + ra_skip = RA_SECTORS - ra_sectors; + } else { + ra_sectors = dmalimit/BPS; + ra_skip = 0; + } + } else { + ra_sectors = RA_SECTORS; + ra_skip=0; + } if (dosdev != ra_dev || sector < ra_first || sector >= ra_end) { int cyl, head, sec, nsec; @@ -161,10 +182,10 @@ Bread(sector, addr) head = (sector % spc) / spt; sec = sector % spt; nsec = spt - sec; - if (nsec > RA_SECTORS) - nsec = RA_SECTORS; + if (nsec > ra_sectors) + nsec = ra_sectors; twiddle(); - while (biosread(dosdev, cyl, head, sec, nsec, ra_buf)) { + while (biosread(dosdev, cyl, head, sec, nsec, ra_buf+ra_skip*BPS)) { printf("Error: C:%d H:%d S:%d\n", cyl, head, sec); nsec = 1; twiddle(); @@ -173,7 +194,7 @@ Bread(sector, addr) ra_first = sector; ra_end = sector + nsec; } - bcopy(ra_buf + (sector - ra_first) * BPS, addr, BPS); + bcopy(ra_buf + (sector - ra_first+ra_skip) * BPS, addr, BPS); } badsect(sector) diff --git a/sys/arch/i386/boot/io.c b/sys/arch/i386/boot/io.c index 30324242c19..aed0e47dda4 100644 --- a/sys/arch/i386/boot/io.c +++ b/sys/arch/i386/boot/io.c @@ -148,9 +148,42 @@ gets(buf) char *buf; { char *ptr = buf; + static char hadchar=0; +#ifdef DOSREAD + /* + * Simulate keyboard input of the command line arguments. + */ + static int first=1; + int hadarg=0; + + if (first) { + char *arg = (char *) 0x80; + int argcnt = *arg++; + while (argcnt && *arg==' ') { + arg++; + argcnt--; + } + while (argcnt--) { + if (*arg>='A' && *arg<='Z') + *arg += 'a' - 'A'; + putchar(*arg); + *ptr++ = *arg++; + hadarg=1; + } + first=0; + } +#endif for (;;) { register int c = getc(); + hadchar=1; +#ifdef DOSREAD + if (c == 3 || c== 27 ) { + printf("Exiting\n"); + dosexit(0); + printf("Exiting failed\n"); + } +#endif if (c == '\n' || c == '\r') { putchar('\n'); *ptr = '\0'; @@ -158,6 +191,13 @@ gets(buf) } else if (c == '\b' || c == '\177') { if (ptr > buf) { putchar('\b'); +#ifdef DOSREAD + if (hadarg) { + putchar('\n'); + *ptr=0; + return 1; + } +#endif putchar(' '); putchar('\b'); ptr--; diff --git a/sys/arch/i386/boot/start.S b/sys/arch/i386/boot/start.S index c70205ed786..288c75326ad 100644 --- a/sys/arch/i386/boot/start.S +++ b/sys/arch/i386/boot/start.S @@ -70,6 +70,7 @@ BOOTABLE = 0x80 # value of boot_ind, means bootable partition ENTRY(boot1) start: +#ifndef DOSREAD # start (aka boot1) is loaded at 0x0:0x7c00 but we want 0x7c0:0 # ljmp to the next instruction to adjust %cs data32 @@ -182,8 +183,13 @@ again: movl $enoboot, %esi data32 jmp err_stop +#else /* !DOSREAD */ + movb $0xff, %dl + jmp _C_LABEL(boot2) +#endif /* DOSREAD */ +#ifndef DOSREAD /* # BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory # Call with %ah = 0x2 @@ -264,6 +270,7 @@ message: data32 pushl %edx +#endif nextb: cld lodsb # load a byte into %al diff --git a/sys/arch/i386/boot/sys.c b/sys/arch/i386/boot/sys.c index f8009aaf4b9..17796ece6d6 100644 --- a/sys/arch/i386/boot/sys.c +++ b/sys/arch/i386/boot/sys.c @@ -60,6 +60,11 @@ _read(buffer, count, copy) int logno, off, size; int cnt2; +#ifdef DOSREAD + extern short doshandle; + if (doshandle>=0) + return __dosread(buffer,count,copy); +#endif while (count) { off = blkoff(fs, poff); logno = lblkno(fs, poff); @@ -85,6 +90,10 @@ find(path) int block, off, loc, ino = ROOTINO, parent; struct dirent *dp; int nlinks = 0; + int list_only = 0; + + if (strcmp(path, "?") == 0) + list_only = 1; loop: iodest = iobuf; @@ -127,7 +136,11 @@ loop: loc = 0; do { if (loc >= inode.i_size) - return 0; + if (list_only) { + putchar('\n'); + return -1; + } else + return 0; if (!(off = blkoff(fs, loc))) { int cnt2; block = lblkno(fs, loc); @@ -143,6 +156,11 @@ loop: return 0; } loc += dp->d_reclen; + if (dp->d_fileno && list_only && + dp->d_type == DT_REG && dp->d_name[0] != '.') { + printf("%s", dp->d_name); + putchar(' '); + } } while (!dp->d_fileno || strcmp(path, dp->d_name)); ino = dp->d_fileno; *(path = rest) = ch; @@ -212,6 +230,11 @@ openrd() printf("Wangtek unsupported\n"); return 1; } +#ifdef DOSREAD + else if (maj == 5) { + return dosopenrd(cp); + } +#endif inode.i_dev = dosdev; /***********************************************\ * Now we know the disk unit and part, * @@ -240,8 +263,12 @@ openrd() /***********************************************\ * Find the actual FILE on the mounted device * \***********************************************/ - if (!find(cp)) + switch(find(cp)) { + case -1: + return -1; + case 0: return 1; + } poff = 0; name = cp; diff --git a/sys/arch/i386/boot/version.c b/sys/arch/i386/boot/version.c index 3d40a95b061..d15e839c8f5 100644 --- a/sys/arch/i386/boot/version.c +++ b/sys/arch/i386/boot/version.c @@ -1,8 +1,13 @@ +/* $OpenBSD: version.c,v 1.3 1996/05/13 09:13:07 mickey Exp $ */ /* $NetBSD: version.c,v 1.28 1995/12/23 17:21:23 perry Exp $ */ /* * NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE. * + * 1.28 -> 1.29 + * adding program for booting from DOS file. + * implement 'list files' (Luke Mewburn <lukem@telstra.com.au>) + * * 1.27 -> 1.28 * fix gets to use real timeout instead of loop and do * a little cleanup, and add some prototypes. A lot more @@ -54,4 +59,4 @@ * look in boot.c revision logs */ -char *version = "1.28"; +char version[] = "1.29"; |