From: Ben Gras Date: Mon, 25 Apr 2011 13:10:57 +0000 (+0200) Subject: made boot/ into hierarchy of programs X-Git-Tag: v3.2.0~565 X-Git-Url: http://zhaoyanbai.com/repos/Bv9ARM.ch04.html?a=commitdiff_plain;h=455b809b1730940ebb1af592e95aa827264167b2;p=minix.git made boot/ into hierarchy of programs work of Antoine Leca --- diff --git a/boot/Makefile b/boot/Makefile index 07571cbe3..f79185e95 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -1,97 +1,17 @@ # Makefile for the boot monitor package. -# XXX: Can only be built with ACK currently -CC:=${CC:C/^.*gcc/cc/} -COMPILER_TYPE:=ack +.include -PROGS= bootblock cdbootblock boot masterboot \ - jumpboot installboot edparams dosboot mkfile +# 16-bit code; various boot blocks +SUBDIR= masterboot bootblock cdbootblock -SRCS.bootblock= bootblock.s -CPPFLAGS.bootblock.s= ${I86CPPFLAGS} -LDFLAGS.bootblock= ${I86LDFLAGS} -BINDIR.bootblock= /usr/mdec -MAN.bootblock= +# Supplementary MBR code (alternate to masterboot) +SUBDIR+= jumpboot -SRCS.cdbootblock= cdbootblock.s -CPPFLAGS.cdbootblock.s= ${I86CPPFLAGS} -DCDBOOT -LDFLAGS.cdbootblock= ${I86LDFLAGS} -BINDIR.cdbootblock= /usr/mdec -MAN.cdbootblock= +# 16-bit code; needs the i86 ACK library +SUBDIR+= boot -SRCS.boot= boothead.s boot.c bootimage.c rawfs86.c -CPPFLAGS.boothead.s= ${I86CPPFLAGS} -CPPFLAGS.boot.c= ${I86CPPFLAGS} -CPPFLAGS.bootimage.c= ${I86CPPFLAGS} -CPPFLAGS.rawfs86.c= ${I86CPPFLAGS} -LDFLAGS.boot= ${I86LDFLAGS} -DPADD.boot= ${LIBSYS} -LDADD.boot= -lsys -BINDIR.boot= /usr/mdec -MAN.boot= +# Userland MINIX code +SUBDIR+= installboot edparams -realall: .PHONY bootsize -bootsize: boot - ${INSTALL} -S 22kb boot - -SRCS.masterboot= masterboot.s -CPPFLAGS.masterboot.s= ${I86CPPFLAGS} -LDFLAGS.masterboot= ${I86LDFLAGS} -BINDIR.masterboot= /usr/mdec -MAN.masterboot= - -SRCS.jumpboot= jumpboot.s -CPPFLAGS.jumpboot.s= ${I86CPPFLAGS} -LDFLAGS.jumpboot= ${I86LDFLAGS} -BINDIR.jumpboot= /usr/mdec -MAN.jumpboot= - -SRCS.installboot= installboot.c rawfs.c -BINDIR.installboot= /usr/bin -MAN.installboot= - -SRCS.edparams= edparams.c rawfs.c -CPPFLAGS.edparams.c= -DUNIX -BINDIR.edparams= /usr/bin -MAN.edparams= - -SRCS.dosboot= doshead.s dosboot.o bootimage.o rawfs86.o -CPPFLAGS.dosboot.c= -DDOS $(I86CPPFLAGS) -LDADD.dosboot= ${I86LDFLAGS} -lsys -BINDIR.dosboot= /usr/mdec -CPPFLAGS.doshead.s= -mi386 -MAN.dosboot= - -SRCS.mkfile= mkfhead.s mkfile.c -CPPFLAGS.mkfile.s= ${I86CPPFLAGS} -LDADD.mkfile= ${I86LDFLAGS} -lsys -BINDIR.mkfile= /usr/mdec -MAN.mkfile= - -rawfs86.c: rawfs.c - ln -f rawfs.c rawfs86.c - -edparams.c: boot.c - ln -f boot.c edparams.c - -dosboot.c: boot.c - ln -f boot.c dosboot.c - -cdbootblock.s: bootblock.s - ln -f bootblock.s cdbootblock.s - -mkfile.com: mkfile - -boot.com: dosboot - ./a.out2com dosboot boot.com - -CPPFLAGS= -I${MINIXSRCDIR} -AFLAGS= -I${MINIXSRCDIR} -I86CPPFLAGS= -mi86 -Was-ncc -I86LDFLAGS= -mi86 -Was-ncc -.o -com - -STRIPFLAG= -s - -CLEANFILES+= rawfs86.c edparams.c cdbootblock.s dosboot.c - -.include +.include diff --git a/boot/a.out2com b/boot/a.out2com deleted file mode 100755 index 4bf450868..000000000 --- a/boot/a.out2com +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh -# -# a.out2com - Minix a.out to DOS .COM Author: Kees J. Bot -# 17 Jun 1995 -# Transform a Minix a.out to the COM format of MS-DOS, -# the executable must be common I&D with 256 scratch bytes at the start of -# the text segment to make space for the Program Segment Prefix. The Minix -# a.out header and these 256 bytes are removed to make a COM file. - -case $# in -2) aout="$1" - com="$2" - ;; -*) echo "Usage: $0 " >&2 - exit 1 -esac - -size "$aout" >/dev/null || exit -set `size "$aout" | sed 1d` -count=`expr \( $1 + $2 - 256 + 31 \) / 32` - -exec dd if="$aout" of="$com" bs=32 skip=9 count=$count conv=silent - -# -# $PchId: a.out2com,v 1.3 1998/08/01 09:13:01 philip Exp $ diff --git a/boot/addaout.c b/boot/addaout.c deleted file mode 100644 index 7f9da98e8..000000000 --- a/boot/addaout.c +++ /dev/null @@ -1,128 +0,0 @@ -/* A small utility to append an a.out header to an arbitrary file. This allows - * inclusion of arbitrary data in the boot image, so that it is magically - * loaded as a RAM disk. The a.out header is structured as follows: - * - * a_flags: A_IMG to indicate this is not an executable - * - * Created: April 2005, Jorrit N. Herder - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define INPUT_FILE 1 -#define OUTPUT_FILE 2 - -/* Report problems. */ -static void report(const char *problem, const char *message) -{ - fprintf(stderr, "%s:\n", problem); - fprintf(stderr, " %s\n\n", message); -} - - -static int copy_data(int srcfd, int dstfd) -{ - char buf[8192]; - ssize_t n; - int total=0; - - /** FIXME: handle error from read() */ - - /* Copy the little bytes themselves. (Source from cp.c). */ - while ((n= read(srcfd, buf, sizeof(buf))) > 0) { - char *bp = buf; - ssize_t r = 0; - - /** FIXME: handle error from write() */ - while (n > 0 && (r= write(dstfd, bp, n)) > 0) { - bp += r; - n -= r; - total += r; - } - if (r == 0) { - fprintf(stderr, "Warning: EOF writing to output file.\n"); - return(-1); - } - } - return(total); -} - - -/* Main program. */ -int main(int argc, char **argv) -{ - struct exec aout; - struct stat stin; - int fdin, fdout; - char * bp; - int n,r; - int total_size; - - /* Check if command line arguments are present, or print usage. */ - if (argc!=3) { - printf("Invalid arguments. Usage:\n"); - printf(" %s \n",argv[0]); - return(1); - } - - /* Check if we can open the input and output file. */ - if (stat(argv[INPUT_FILE], &stin) != 0) { - report("Couldn't get status of input file", strerror(errno)); - return(1); - } - if ((fdin = open(argv[INPUT_FILE], O_RDONLY)) < 0) { - report("Couldn't open input file", strerror(errno)); - return(1); - } - if ((fdout = open(argv[OUTPUT_FILE], O_WRONLY|O_CREAT|O_TRUNC, - stin.st_mode & 0777)) < 0) { - report("Couldn't open output file", strerror(errno)); - return(1); - } - - - /* Copy input file to output file, but leave space for a.out header. */ - lseek(fdout, sizeof(aout), SEEK_SET); - total_size = copy_data(fdin, fdout); - if (total_size < 0) { - report("Aborted", "Output file may be truncated."); - return(1); - } else if (total_size == 0) { - report("Aborted without prepending header", "No data in input file."); - return(1); - } - - - /* Build a.out header and write to output file. */ - memset(&aout, 0, sizeof(struct exec)); - aout.a_magic[0] = A_MAGIC0; - aout.a_magic[1] = A_MAGIC1; - aout.a_flags |= A_IMG; - aout.a_hdrlen = sizeof(aout); - aout.a_text = 0; - aout.a_data = total_size; - aout.a_bss = 0; - aout.a_total = aout.a_hdrlen + aout.a_data; - - bp = (char *) &aout; - n = sizeof(aout); - lseek(fdout, 0L, SEEK_SET); - while (n > 0 && (r= write(fdout, bp, n)) > 0) { - bp += r; - n -= r; - } - - printf("Prepended data file (%d bytes) with a.out header (%u bytes).\n", - total_size, sizeof(aout)); - printf("Done.\n"); - - return(0); -} - diff --git a/boot/boot/Makefile b/boot/boot/Makefile new file mode 100644 index 000000000..c2432003d --- /dev/null +++ b/boot/boot/Makefile @@ -0,0 +1,27 @@ +# boot monitor: runs in 16-bit mode +.include + +# XXX: Can only be built with ACK currently +.include "${.CURDIR}/../minix.ack16.mk" +AFLAGS+= -Was-ncc +#LDFLAGS+= -stack 12kb +STRIPFLAG= -s +LIBDIR?= /usr/lib/i86 + +PROG= boot + +SRCS= boothead.s boot.c bootimage.c rawfs.c +.PATH: ${.CURDIR}/.. +CPPFLAGS+= -I${MINIXSRCDIR} -I${.CURDIR} -I${.CURDIR}/.. + +DPADD+= ${LIBSYS} # for kprintf, kmalloc +LDADD+= -lsys + +BINDIR= /usr/mdec +MAN= + +.include + +realall: .PHONY bootsize +bootsize: boot + ${INSTALL} -S 12kb boot diff --git a/boot/boot.c b/boot/boot/boot.c similarity index 100% rename from boot/boot.c rename to boot/boot/boot.c diff --git a/boot/boothead.s b/boot/boot/boothead.s similarity index 100% rename from boot/boothead.s rename to boot/boot/boothead.s diff --git a/boot/bootimage.c b/boot/boot/bootimage.c similarity index 100% rename from boot/bootimage.c rename to boot/boot/bootimage.c diff --git a/boot/bootblock/Makefile b/boot/bootblock/Makefile new file mode 100644 index 000000000..401a14404 --- /dev/null +++ b/boot/bootblock/Makefile @@ -0,0 +1,19 @@ +# bootblock: secondary boot code, still 16-bit mode + +.include + +# XXX: Can only be built with ACK currently +.include "${MINIXSRCDIR}/boot/minix.ack16.mk" +AFLAGS+= -Was-ncc +STRIPFLAG= -s + +PROG= bootblock + +SRCS= bootblock.s + +BINDIR= /usr/mdec +MAN= + +LIBC= # defined, to silence bsd.*.mk + +.include diff --git a/boot/bootblock.s b/boot/bootblock/bootblock.s similarity index 100% rename from boot/bootblock.s rename to boot/bootblock/bootblock.s diff --git a/boot/cdbootblock/Makefile b/boot/cdbootblock/Makefile new file mode 100644 index 000000000..3dc0ba0d3 --- /dev/null +++ b/boot/cdbootblock/Makefile @@ -0,0 +1,21 @@ +# cdbootblock: secondary boot code, when booting from cd-rom + +.include + +# XXX: Can only be built with ACK currently +.include "${MINIXSRCDIR}/boot/minix.ack16.mk" +AFLAGS+= -Was-ncc +STRIPFLAG= -s + +PROG= cdbootblock + +SRCS= bootblock.s +.PATH: ${.CURDIR}/../bootblock +CPPFLAGS+= -DCDBOOT + +BINDIR= /usr/mdec +MAN= + +LIBC= # defined, to silence bsd.*.mk + +.include diff --git a/boot/doshead.s b/boot/doshead.s deleted file mode 100644 index 74b7dd4fc..000000000 --- a/boot/doshead.s +++ /dev/null @@ -1,1380 +0,0 @@ -! Doshead.s - DOS & BIOS support for boot.c Author: Kees J. Bot -! -! -! This file contains the startup and low level support for the secondary -! boot program. It contains functions for disk, tty and keyboard I/O, -! copying memory to arbitrary locations, etc. -! -! This runs under MS-DOS as a .COM file. A .COM file is what Minix calls -! a common I&D executable, except that the first 256 bytes contains DOS -! thingies. -! -.sect .text; .sect .rom; .sect .data; .sect .bss - - K_I386 = 0x0001 ! Call Minix in 386 mode - STACK = 16384 ! Number of bytes for the stack - - DS_SELECTOR = 3*8 ! Kernel data selector - ES_SELECTOR = 4*8 ! Flat 4 Gb - SS_SELECTOR = 5*8 ! Monitor stack - CS_SELECTOR = 6*8 ! Kernel code - MCS_SELECTOR= 7*8 ! Monitor code - - ESC = 0x1B ! Escape character - -! Imported variables and functions: -.extern _caddr, _daddr, _runsize, _edata, _end ! Runtime environment -.extern _k_flags ! Special kernel flags -.extern _mem ! Free memory list -.extern _vdisk ! Name of the virtual disk - -.sect .text - -.use16 ! Tell 386 assembler we're in 16-bit mode - -.define _PSP -_PSP: - .space 256 ! Program Segment Prefix - -dosboot: - cld ! C compiler wants UP - xor ax, ax ! Zero - mov di, _edata ! Start of bss is at end of data - mov cx, _end ! End of bss (begin of heap) - sub cx, di ! Number of bss bytes - shr cx, 1 ! Number of words - rep stos ! Clear bss - cmp sp, _end+STACK - jb 0f - mov sp, _end+STACK ! "chmem" to 16 kb -0: - -! Are we called with the /U option? - movb cl, (_PSP+0x80) ! Argument byte count - xorb ch, ch - mov bx, _PSP+0x81 ! Argument string -0: jcxz notuflag - cmpb (bx), 0x20 ! Whitespace? - ja 1f - inc bx - dec cx - jmp 0b -1: cmp cx, 2 ! '/U' is two bytes - jne notuflag - cmpb (bx), 0x2F ! '/'? - jne notuflag - movb al, 1(bx) - andb al, ~0x20 ! Ignore case - cmpb al, 0x55 ! 'U'? - jne notuflag - jmp keepumb ! Go grab an UMB -notuflag: - -! Remember the current video mode for restoration on exit. - movb ah, 0x0F ! Get current video mode - int 0x10 - andb al, 0x7F ! Mask off bit 7 (no blanking) - movb (old_vid_mode), al - movb (cur_vid_mode), al - -! We require at least MS-DOS 3.0. - mov ax, 0x3000 ! Get DOS version - int 0x21 - cmpb al, 3 ! DOS 3.0+ ? - jae dosok - push tellbaddos - call _printf - jmp quit -.sect .rom -tellbaddos: .ascii "MS-DOS 3.0 or better required\n\0" -.sect .text -dosok: - -! Find out how much "low" memory there is available, where it starts and -! where it ends. - mov di, _mem ! di = memory list - mov ax, _PSP+0x80 ! From PSP:80 to next PSP is ours - mov dx, ds - call seg2abs - mov (di), ax - mov 2(di), dx ! mem[0].base = ds * 16 + 0x80 - xor ax, ax - mov dx, (_PSP+2) ! First in-use segment far above us - call seg2abs - sub ax, (di) - sbb dx, 2(di) ! Minus base gives size - mov 4(di), ax - mov 6(di), dx ! mem[1].size = free low memory size - -! Give C code access to the code segment, data segment and the size of this -! process. - xor ax, ax - mov dx, cs - call seg2abs - mov (_caddr+0), ax - mov (_caddr+2), dx - xor ax, ax - mov dx, ds - call seg2abs - mov (_daddr+0), ax - mov (_daddr+2), dx - mov ax, sp - mov dx, ss ! End of stack = end of program - call seg2abs - sub ax, (_caddr+0) - sbb dx, (_caddr+2) ! Minus start of our code - mov (_runsize+0), ax - mov (_runsize+2), dx ! Is our size - -! Patch the regular _getprocessor library routine to jump to 'getprocessor', -! that checks if we happen to be in a V8086 straightjacket by returning '86'. - cseg movb (_getprocessor+0), 0xE9 - mov ax, getprocessor - sub ax, _getprocessor+3 - cseg mov (_getprocessor+1), ax - -! Grab the largest chunk of extended memory available. - call _getprocessor - cmp ax, 286 ! Only 286s and above have extended memory - jb no_ext - mov ax, 0x4300 ! XMS driver check - int 0x2F - cmpb al, 0x80 ! XMS driver exists? - je xmsthere -get_ext: ! No driver, so can use all ext memory directly - call _getprocessor - cmp ax, 486 ! Assume 486s were the first to have >64M - jb small_ext ! (It helps to be paranoid when using the BIOS) -big_ext: - mov ax, 0xE801 ! Code for get memory size for >64M - int 0x15 ! ax = mem at 1M per 1K, bx = mem at 16M per 64K - jnc got_ext -small_ext: - movb ah, 0x88 ! Code for get extended memory size - clc ! Carry will stay clear if call exists - int 0x15 ! Returns size (in K) in ax for AT's - jc no_ext - test ax, ax ! An AT with no extended memory? - jz no_ext - xor bx, bx ! bx = mem above 16M per 64K = 0 -got_ext: - mov cx, ax ! cx = copy of ext mem at 1M - mov 10(di), 0x0010 ! mem[1].base = 0x00100000 (1M) - mul (c1024) - mov 12(di), ax ! mem[1].size = "ext mem at 1M" * 1024 - mov 14(di), dx - test bx, bx - jz no_ext ! No more ext mem above 16M? - cmp cx, 15*1024 ! Chunks adjacent? (precisely 15M at 1M?) - je adj_ext - mov 18(di), 0x0100 ! mem[2].base = 0x01000000 (16M) - mov 22(di), bx ! mem[2].size = "ext mem at 16M" * 64K - jmp no_ext -adj_ext: - add 14(di), bx ! Add ext mem above 16M to mem below 16M -no_ext: - jmp gotxms - -xmsthere: - mov ax, 0x4310 ! Get XMS driver address - int 0x2F - mov (xms_driver+0), bx - mov (xms_driver+2), es - push ds - pop es - movb ah, 0x08 ! Query free extended memory - xorb bl, bl - callf (xms_driver) - testb bl, bl - jnz xmserr - push ax ! ax = size of largest block in kb - mul (c1024) - mov 12(di), ax - mov 14(di), dx ! mem[1].size = ax * 1024 - pop dx ! dx = size of largest block in kb - movb ah, 0x09 ! Allocate XMS block of size dx - callf (xms_driver) - test ax, ax - jz xmserr - mov (xms_handle), dx ! Save handle - movb ah, 0x0C ! Lock XMS block (handle in dx) - callf (xms_driver) - test ax, ax - jz xmserr - mov 8(di), bx - mov 10(di), dx ! mem[1].base = Address of locked block -gotxms: - -! If we're running in a DOS box then they're might be an Upper Memory Block -! we can use. Every little bit helps when in real mode. - mov ax, 20(di) - or ax, 22(di) ! Can we use mem[2]? - jnz gotumb - mov dx, 0xFFFF ! dx = Maximum size, i.e. gimme all - call getumb ! Get UMB, dx = segment, cx = length - test cx, cx ! Did we get a block? - jz gotumb - xor ax, ax ! dx:ax = memory block - call seg2abs - mov 16(di), ax - mov 18(di), dx ! mem[2].base = memory block base - mov dx, cx - xor ax, ax ! dx:ax = length of memory block - call seg2abs - mov 20(di), ax - mov 22(di), dx ! mem[2].size = memory block length -gotumb: - -! Set up an INT 24 "critical error" handler that returns "fail". This way -! Minix won't suffer from "(A)bort, (R)etry, (I)nfluence with a large hammer?". - mov (0x007C), 0x03B0 ! movb al, 0x03 (fail code) - movb (0x007E), 0xCF ! iret - movb ah, 0x25 ! Set interrupt vector - mov dx, 0x007C ! ds:dx = ds:0x007C = interrupt handler - int 0x21 - -! Time to switch to a higher level language (not much higher) - call _boot - -! void ..exit(int status) -! Exit the monitor by returning to DOS. -.define _exit, __exit, ___exit ! Make various compilers happy -_exit: -__exit: -___exit: - mov dx, (xms_handle) - cmp dx, -1 ! Is there an ext mem block in use? - je nohandle - movb ah, 0x0D ! Unlock extended memory block - callf (xms_driver) - mov dx, (xms_handle) - movb ah, 0x0A ! Free extended memory block - callf (xms_driver) -nohandle: - call restore_video - pop ax - pop ax ! Return code in al - movb ah, 0x4C ! Terminate with return code - int 0x21 - -quit: ! exit(1) - movb al, 1 - push ax - call _exit - -xmserr: - xorb bh, bh - push bx - push tellxmserr - call _printf - jmp quit -.sect .rom -tellxmserr: .ascii "Extended memory problem, error 0x%02x\n\0" -.sect .text - -! int getprocessor(void) -! Prefix for the regular _getprocessor call that first checks if we're -! running in a virtual 8086 box. -getprocessor: - push sp ! Is pushed sp equal to sp? - pop ax - cmp ax, sp - jne gettrueproc ! If not then it's a plain 8086 or 80186 - .data1 0x0F,0x01,0xE0 ! Use old 286 SMSW instruction to get the MSW - testb al, 0x01 ! Protected mode enabled? - jz gettrueproc ! If not then a 286 or better in real mode - mov ax, 86 ! Forget fancy tricks, say it's an 8086 - ret -gettrueproc: ! Get the true processor type - push bp ! _getprocessor prologue that is patched over. - mov bp, sp - jmp _getprocessor+3 - -! Try to get an Upper Memory Block under MS-DOS 5+. Try to get one up to size -! dx, return segment of UMB found in dx and size in paragraphs in cx. -getumb: - xor cx, cx ! Initially nothing found - mov ax, 0x3000 ! Get DOS version - int 0x21 - cmpb al, 5 ! MS-DOS 5.0 or better? - jb retumb - mov ax, 0x544D ! Get UMB kept by BOOT /U - int 0x15 ! Returns dx = segment, cx = size - jc 0f - cmp ax, 0x4D54 ! Carry clear and ax byte swapped? - je retumb -0: mov ax, 0x5802 ! Get UMB link state - int 0x21 - xorb ah, ah - push ax ! Save UMB link state - mov ax, 0x5803 ! Set UMB link state - mov bx, 0x0001 ! Add UMBs to DOS memory chain - int 0x21 - mov ax, 0x5800 ! Get memory allocation strategy - int 0x21 - push ax ! Save allocation strategy - mov ax, 0x5801 ! Set memory allocation strategy - mov bx, 0x0080 ! First fit, try high then low memory - int 0x21 - movb ah, 0x48 ! Allocate memory - mov bx, dx ! Number of paragraphs wanted - int 0x21 ! Fails with bx = size of largest - jnc 0f ! Succeeds with ax = allocated block - test bx, bx ! Is there any? - jz no_umb - movb ah, 0x48 ! Allocate memory - int 0x21 - jc no_umb ! Did we get some? -0: mov dx, ax ! dx = segment - mov cx, bx ! cx = size -no_umb: mov ax, 0x5801 ! Set memory allocation strategy - pop bx ! bx = saved former strategy - int 0x21 - mov ax, 0x5803 ! Set UMB link state - pop bx ! bx = saved former link state - int 0x21 -retumb: ret - -! 'BOOT /U' instructs this program to grab the biggest available UMB and to -! sit on it until the next invocation of BOOT wants it back. These shenanigans -! are necessary because Windows 95 keeps all UMBs to itself unless you get hold -! of them first. - umb = 0x80 ! UMB base and size - old15 = 0x84 ! Old 15 interrupt vector - new15 = 0x88 ! New 15 interrupt handler -keepumb: - mov ax, 0x544D ! "Keep UMB" handler already present? - int 0x15 - jc 0f - cmp ax, 0x4D54 - je exitumb ! Already present, so quit -0: - mov si, new15start - mov di, new15 - mov cx, new15end - sub cx, si - rep movsb ! Copy handler into place - add di, 15 - movb cl, 4 - shr di, cl ! di = first segment above handler - mov cx, cs - cmp cx, 0xA000 ! Are we loaded high perchance? - jb nothigh -werehigh: - add cx, di - mov (umb+0), cx ! Use my own memory as the UMB to keep - mov ax, (_PSP+2) ! Up to the next in-use segment - sub ax, dx ! ax = size of my free memory - cmp ax, 0x1000 ! At least 64K? - jb exitumb ! Don't bother if less - mov (umb+2), 0x1000 ! Size of UMB - add di, 0x1000 ! Keep my code plus 64K when TSR - jmp hook15 -nothigh: - mov dx, 0x1000 - call getumb ! Grab an UMB of at most 64K - cmp cx, 0x1000 ! Did we get 64K? - jb exitumb ! Otherwise don't bother - mov (umb+0), dx - mov (umb+2), cx -hook15: - mov ax, 0x3515 ! Get interrupt vector - int 0x21 - mov (old15+0), bx - mov (old15+2), es ! Old 15 interrupt - mov ax, 0x2515 ! Set interrupt vector - mov dx, new15 ! ds:dx = new 15 handler - int 0x21 - mov ax, 0x3100 ! Terminate and stay resident - mov dx, di ! dx = di = paragraphs we keep - int 0x21 -exitumb: - mov ax, 0x4C00 ! exit(0) - int 0x21 - -new15start: ! New interrupt 15 handler - pushf - cmp ax, 0x544D ! Is it my call? - je my15 - popf - cseg jmpf (old15) ! No, continue with old 15 -my15: popf - push bp - mov bp, sp - andb 6(bp), ~0x01 ! clear carry, call will succeed - xchgb al, ah ! ax = 4D54, also means call works - cseg mov dx, (umb+0) ! dx = base of UMB - cseg mov cx, (umb+2) ! cx = size of UMB - pop bp - iret ! return to caller -new15end: - -! u32_t mon2abs(void *ptr) -! Address in monitor data to absolute address. -.define _mon2abs -_mon2abs: - mov bx, sp - mov ax, 2(bx) ! ptr - mov dx, ds ! Monitor data segment - !jmp seg2abs - -seg2abs: ! Translate dx:ax to the 32 bit address dx-ax - push cx - movb ch, dh - movb cl, 4 - shl dx, cl - shrb ch, cl ! ch-dx = dx << 4 - add ax, dx - adcb ch, 0 ! ch-ax = ch-dx + ax - movb dl, ch - xorb dh, dh ! dx-ax = ch-ax - pop cx - ret - -abs2seg: ! Translate the 32 bit address dx-ax to dx:ax - push cx - movb ch, dl - mov dx, ax ! ch-dx = dx-ax - and ax, 0x000F ! Offset in ax - movb cl, 4 - shr dx, cl - shlb ch, cl - orb dh, ch ! dx = ch-dx >> 4 - pop cx - ret - -! void raw_copy(u32_t dstaddr, u32_t srcaddr, u32_t count) -! Copy count bytes from srcaddr to dstaddr. Don't do overlaps. -! Also handles copying words to or from extended memory. -.define _raw_copy -_raw_copy: - push bp - mov bp, sp - push si - push di ! Save C variable registers -copy: - cmp 14(bp), 0 - jnz bigcopy - mov cx, 12(bp) - jcxz copydone ! Count is zero, end copy - cmp cx, 0xFFF0 - jb smallcopy -bigcopy:mov cx, 0xFFF0 ! Don't copy more than about 64K at once -smallcopy: - push cx ! Save copying count - mov ax, 4(bp) - mov dx, 6(bp) - cmp dx, 0x0010 ! Copy to extended memory? - jae ext_copy - cmp 10(bp), 0x0010 ! Copy from extended memory? - jae ext_copy - call abs2seg - mov di, ax - mov es, dx ! es:di = dstaddr - mov ax, 8(bp) - mov dx, 10(bp) - call abs2seg - mov si, ax - mov ds, dx ! ds:si = srcaddr - shr cx, 1 ! Words to move - rep movs ! Do the word copy - adc cx, cx ! One more byte? - rep movsb ! Do the byte copy - mov ax, ss ! Restore ds and es from the remaining ss - mov ds, ax - mov es, ax - jmp copyadjust -ext_copy: - mov (x_dst_desc+2), ax - movb (x_dst_desc+4), dl ! Set base of destination segment - mov ax, 8(bp) - mov dx, 10(bp) - mov (x_src_desc+2), ax - movb (x_src_desc+4), dl ! Set base of source segment - mov si, x_gdt ! es:si = global descriptor table - shr cx, 1 ! Words to move - movb ah, 0x87 ! Code for extended memory move - int 0x15 -copyadjust: - pop cx ! Restore count - add 4(bp), cx - adc 6(bp), 0 ! srcaddr += copycount - add 8(bp), cx - adc 10(bp), 0 ! dstaddr += copycount - sub 12(bp), cx - sbb 14(bp), 0 ! count -= copycount - jmp copy ! and repeat -copydone: - pop di - pop si ! Restore C variable registers - pop bp - ret - -! u16_t get_word(u32_t addr); -! void put_word(u32_t addr, u16_t word); -! Read or write a 16 bits word at an arbitrary location. -.define _get_word, _put_word -_get_word: - mov bx, sp - call gp_getaddr - mov ax, (bx) ! Word to get from addr - jmp gp_ret -_put_word: - mov bx, sp - push 6(bx) ! Word to store at addr - call gp_getaddr - pop (bx) ! Store the word - jmp gp_ret -gp_getaddr: - mov ax, 2(bx) - mov dx, 4(bx) - call abs2seg - mov bx, ax - mov ds, dx ! ds:bx = addr - ret -gp_ret: - push es - pop ds ! Restore ds - ret - -! void relocate(void); -! After the program has copied itself to a safer place, it needs to change -! the segment registers. Caddr has already been set to the new location. -.define _relocate -_relocate: - pop bx ! Return address - mov ax, (_caddr+0) - mov dx, (_caddr+2) - call abs2seg - mov cx, dx ! cx = new code segment - mov ax, cs ! Old code segment - sub ax, cx ! ax = -(new - old) = -Moving offset - mov dx, ds - sub dx, ax - mov ds, dx ! ds += (new - old) - mov es, dx - mov ss, dx - xor ax, ax - call seg2abs - mov (_daddr+0), ax - mov (_daddr+2), dx ! New data address - push cx ! New text segment - push bx ! Return offset of this function - retf ! Relocate - -! void *brk(void *addr) -! void *sbrk(size_t incr) -! Cannot fail implementations of brk(2) and sbrk(3), so we can use -! malloc(3). They reboot on stack collision instead of returning -1. -.sect .data - .align 2 -break: .data2 _end ! A fake heap pointer -.sect .text -.define _brk, __brk, _sbrk, __sbrk -_brk: -__brk: ! __brk is for the standard C compiler - xor ax, ax - jmp sbrk ! break= 0; return sbrk(addr); -_sbrk: -__sbrk: - mov ax, (break) ! ax= current break -sbrk: push ax ! save it as future return value - mov bx, sp ! Stack is now: (retval, retaddr, incr, ...) - add ax, 4(bx) ! ax= break + increment - mov (break), ax ! Set new break - lea dx, -1024(bx) ! sp minus a bit of breathing space - cmp dx, ax ! Compare with the new break - jb heaperr ! Suffocating noises - pop ax ! Return old break (0 for brk) - ret -heaperr:push nomem - call _printf - call quit -.sect .rom -nomem: .ascii "\nOut of memory\n\0" -.sect .text - -! int dev_open(void); -! Open file 'vdisk' to use as the Minix virtual disk. Store handle in -! vfd. Returns 0 for success, otherwise the DOS error code. -.define _dev_open -_dev_open: - call _dev_close ! If already open then first close - mov dx, (_vdisk) ! ds:dx = Address of file name - mov ax, 0x3D22 ! Open file read-write & deny write - int 0x21 - jnc opok ! Open succeeded? - cmp ax, 5 ! Open failed, "access denied"? - jne opbad - mov ax, 0x3D40 ! Open file read-only - int 0x21 - jc opbad -opok: mov (vfd), ax ! File handle to open file - xor ax, ax ! Zero for success -opbad: ret - -! int dev_close(void); -! Close the dos virtual disk. -.define _dev_close -_dev_close: - mov bx, -1 - cmp (vfd), bx ! Already closed? - je 1f - movb ah, 0x3E ! Close file - xchg bx, (vfd) ! bx = vfd; vfd = -1; - int 0x21 - jc 0f -1: xor ax, ax -0: ret - -! int dev_boundary(u32_t sector); -! Returns false; files have no visible boundaries. -.define _dev_boundary -_dev_boundary: - xor ax, ax - ret - -! int biosreadsectors(u32_t bufaddr, u32_t sector, u8_t count) -! int writesectors(u32_t bufaddr, u32_t sector, u8_t count) -! Read/write several sectors from/to the Minix virtual disk. Count -! must fit in a byte. The external variable vfd is the file handle. -! Returns 0 for success, otherwise the DOS error code. -! -.define _biosreadsectors, _writesectors -_writesectors: - push bp - mov bp, sp - movb 13(bp), 0x40 ! Code for a file write - jmp rwsec -_biosreadsectors: - push bp - mov bp, sp - movb 13(bp), 0x3F ! Code for a file read -rwsec: - cmp (vfd), -1 ! Currently closed? - jne 0f - call _dev_open ! Open file if needed - test ax, ax - jnz rwerr -0: mov dx, 8(bp) - mov bx, 10(bp) ! bx-dx = Sector number - mov cx, 9 -mul512: shl dx, 1 - rcl bx, 1 ! bx-dx *= 512 - loop mul512 - mov cx, bx ! cx-dx = Byte position in file - mov bx, (vfd) ! bx = File handle - mov ax, 0x4200 ! Lseek absolute - int 0x21 - jb rwerr - mov bx, (vfd) ! bx = File handle - mov ax, 4(bp) - mov dx, 6(bp) ! dx-ax = Address to transfer data to/from - call abs2seg - mov ds, dx - mov dx, ax ! ds:dx = Address to transfer data to/from - xorb cl, cl - movb ch, 12(bp) ! ch = Number of sectors to transfer - shl cx, 1 ! cx = Number of bytes to transfer - push cx ! Save count - movb ah, 13(bp) ! Read or write - int 0x21 - pop cx ! Restore count - push es - pop ds ! Restore ds - jb rwerr - cmp ax, cx ! All bytes transferred? - je rwall - mov ax, 0x05 ! The DOS code for "I/O error", but different - jmp rwerr -rwall: call wheel ! Display tricks - xor ax, ax -rwerr: pop bp - ret - -! int getch(void); -! Read a character from the keyboard, and check for an expired timer. -! A carriage return is changed into a linefeed for UNIX compatibility. -.define _getch -_getch: - xor ax, ax - xchg ax, (unchar) ! Ungotten character? - test ax, ax - jnz gotch -getch: hlt ! Play dead until interrupted (see pause()) - movb ah, 0x01 ! Keyboard status - int 0x16 - jnz press ! Keypress? - call _expired ! Timer expired? - test ax, ax - jz getch - mov ax, ESC ! Return ESC - ret -press: - xorb ah, ah ! Read character from keyboard - int 0x16 - cmpb al, 0x0D ! Carriage return? - jnz nocr - movb al, 0x0A ! Change to linefeed -nocr: cmpb al, ESC ! Escape typed? - jne noesc - inc (escape) ! Set flag -noesc: xorb ah, ah ! ax = al -gotch: ret - -! int ungetch(void); -! Return a character to undo a getch(). -.define _ungetch -_ungetch: - mov bx, sp - mov ax, 2(bx) - mov (unchar), ax - ret - -! int escape(void); -! True if ESC has been typed. -.define _escape -_escape: - movb ah, 0x01 ! Keyboard status - int 0x16 - jz escflg ! Keypress? - cmpb al, ESC ! Escape typed? - jne escflg - xorb ah, ah ! Discard the escape - int 0x16 - inc (escape) ! Set flag -escflg: xor ax, ax - xchg ax, (escape) ! Escape typed flag - ret - -! int putch(int c); -! Write a character in teletype mode. The putk synonym is -! for the kernel printf function that uses it. -! Newlines are automatically preceded by a carriage return. -! -.define _putch, _putk -_putch: -_putk: mov bx, sp - movb al, 2(bx) ! al = character to be printed - testb al, al ! Kernel printf adds a null char to flush queue - jz nulch - cmpb al, 0x0A ! al = newline? - jnz putc - movb al, 0x20 ! Erase wheel and do a carriage return - call plotc ! plotc(' '); -nodirt: movb al, 0x0D - call putc ! putc('\r') - movb al, 0x0A ! Restore the '\n' and print it -putc: movb ah, 0x0E ! Print character in teletype mode - mov bx, 0x0001 ! Page 0, foreground color - int 0x10 ! Call BIOS VIDEO_IO -nulch: ret - -! |/-\|/-\|/-\|/-\|/-\ (playtime) -wheel: mov bx, (gp) - movb al, (bx) - inc bx ! al = *gp++; - cmp bx, glyphs+4 - jne 0f - mov bx, glyphs -0: mov (gp), bx ! gp= gp == glyphs + 4 ? glyphs : gp; - !jmp plotc -plotc: movb ah, 0x0A ! 0x0A = write character at cursor - mov bx, 0x0001 ! Page 0, foreground color - mov cx, 0x0001 ! Just one character - int 0x10 - ret -.sect .data - .align 2 -gp: .data2 glyphs -glyphs: .ascii "|/-\\" -.sect .text - -! void pause(void); -! Wait for an interrupt using the HLT instruction. This either saves -! power, or tells an x86 emulator that nothing is happening right now. -.define _pause -_pause: - hlt - ret - -! void set_mode(unsigned mode); -! void clear_screen(void); -! Set video mode / clear the screen. -.define _set_mode, _clear_screen -_set_mode: - mov bx, sp - mov ax, 2(bx) ! Video mode - cmp ax, (cur_vid_mode) - je modeok ! Mode already as requested? - mov (cur_vid_mode), ax -_clear_screen: - mov ax, (cur_vid_mode) - andb ah, 0x7F ! Test bits 8-14, clear bit 15 (8x8 flag) - jnz xvesa ! VESA extended mode? - int 0x10 ! Reset video (ah = 0) - jmp mdset -xvesa: mov bx, ax ! bx = extended mode - mov ax, 0x4F02 ! Reset video - int 0x10 -mdset: testb (cur_vid_mode+1), 0x80 - jz setcur ! 8x8 font requested? - mov ax, 0x1112 ! Load ROM 8 by 8 double-dot patterns - xorb bl, bl ! Load block 0 - int 0x10 -setcur: xor dx, dx ! dl = column = 0, dh = row = 0 - xorb bh, bh ! Page 0 - movb ah, 0x02 ! Set cursor position - int 0x10 -modeok: ret - -restore_video: ! To restore the video mode on exit - movb al, 0x20 - call plotc ! Erase wheel - push (old_vid_mode) - call _set_mode - pop ax - ret - -! u32_t get_tick(void); -! Return the current value of the clock tick counter. This counter -! increments 18.2 times per second. Poll it to do delays. Does not -! work on the original PC, but works on the PC/XT. -.define _get_tick -_get_tick: - xorb ah, ah ! Code for get tick count - int 0x1A - mov ax, dx - mov dx, cx ! dx:ax = cx:dx = tick count - ret - - -! Functions used to obtain info about the hardware. Boot uses this information -! itself, but will also pass them on to a pure 386 kernel, because one can't -! make BIOS calls from protected mode. The video type could probably be -! determined by the kernel too by looking at the hardware, but there is a small -! chance on errors that the monitor allows you to correct by setting variables. - -.define _get_bus ! returns type of system bus -.define _get_video ! returns type of display - -! u16_t get_bus(void) -! Return type of system bus, in order: XT, AT, MCA. -_get_bus: - call gettrueproc - xor dx, dx ! Assume XT - cmp ax, 286 ! An AT has at least a 286 - jb got_bus - inc dx ! Assume AT - movb ah, 0xC0 ! Code for get configuration - int 0x15 - jc got_bus ! Carry clear and ah = 00 if supported - testb ah, ah - jne got_bus - eseg movb al, 5(bx) ! Load feature byte #1 - inc dx ! Assume MCA - testb al, 0x02 ! Test bit 1 - "bus is Micro Channel" - jnz got_bus - dec dx ! Assume AT - testb al, 0x40 ! Test bit 6 - "2nd 8259 installed" - jnz got_bus - dec dx ! It is an XT -got_bus: - push ds - pop es ! Restore es - mov ax, dx ! Return bus code - mov (bus), ax ! Keep bus code, A20 handler likes to know - ret - -! u16_t get_video(void) -! Return type of display, in order: MDA, CGA, mono EGA, color EGA, -! mono VGA, color VGA. -_get_video: - mov ax, 0x1A00 ! Function 1A returns display code - int 0x10 ! al = 1A if supported - cmpb al, 0x1A - jnz no_dc ! No display code function supported - - mov ax, 2 - cmpb bl, 5 ! Is it a monochrome EGA? - jz got_video - inc ax - cmpb bl, 4 ! Is it a color EGA? - jz got_video - inc ax - cmpb bl, 7 ! Is it a monochrome VGA? - jz got_video - inc ax - cmpb bl, 8 ! Is it a color VGA? - jz got_video - -no_dc: movb ah, 0x12 ! Get information about the EGA - movb bl, 0x10 - int 0x10 - cmpb bl, 0x10 ! Did it come back as 0x10? (No EGA) - jz no_ega - - mov ax, 2 - cmpb bh, 1 ! Is it monochrome? - jz got_video - inc ax - jmp got_video - -no_ega: int 0x11 ! Get bit pattern for equipment - and ax, 0x30 ! Isolate color/mono field - sub ax, 0x30 - jz got_video ! Is it an MDA? - mov ax, 1 ! No it's CGA - -got_video: - ret - - -! Function to leave the boot monitor and run Minix. -.define _minix - -! void minix(u32_t koff, u32_t kcs, u32_t kds, -! char *bootparams, size_t paramsize, u32_t aout); -_minix: - push bp - mov bp, sp ! Pointer to arguments - - mov dx, 0x03F2 ! Floppy motor drive control bits - movb al, 0x0C ! Bits 4-7 for floppy 0-3 are off - outb dx ! Kill the motors - push ds - xor ax, ax ! Vector & BIOS data segments - mov ds, ax - andb (0x043F), 0xF0 ! Clear diskette motor status bits of BIOS - pop ds - cli ! No more interruptions - - test (_k_flags), K_I386 ! Minix-386? - jnz minix386 - -! Call Minix in real mode. -minix86: - push 22(bp) ! Address of a.out headers - push 20(bp) - - push 18(bp) ! # bytes of boot parameters - push 16(bp) ! Address of boot parameters - - mov dx, cs ! Monitor far return address - mov ax, ret86 - cmp (_mem+14), 0 ! Any extended memory? (mem[1].size > 0 ?) - jnz 0f - xor dx, dx ! If no ext mem then monitor not preserved - xor ax, ax -0: push dx ! Push monitor far return address or zero - push ax - - mov ax, 8(bp) - mov dx, 10(bp) - call abs2seg - push dx ! Kernel code segment - push 4(bp) ! Kernel code offset - mov ax, 12(bp) - mov dx, 14(bp) - call abs2seg - mov ds, dx ! Kernel data segment - mov es, dx ! Set es to kernel data too - retf ! Make a far call to the kernel - -! Call 386 Minix in 386 mode. -minix386: - cseg mov (cs_real-2), cs ! Patch CS and DS into the instructions that - cseg mov (ds_real-2), ds ! reload them when switching back to real mode - mov eax, cr0 - orb al, 0x01 ! Set PE (protection enable) bit - o32 mov (msw), eax ! Save as protected mode machine status word - - mov dx, ds ! Monitor ds - mov ax, p_gdt ! dx:ax = Global descriptor table - call seg2abs - mov (p_gdt_desc+2), ax - movb (p_gdt_desc+4), dl ! Set base of global descriptor table - - mov ax, 12(bp) - mov dx, 14(bp) ! Kernel ds (absolute address) - mov (p_ds_desc+2), ax - movb (p_ds_desc+4), dl ! Set base of kernel data segment - - mov dx, ss ! Monitor ss - xor ax, ax ! dx:ax = Monitor stack segment - call seg2abs ! Minix starts with the stack of the monitor - mov (p_ss_desc+2), ax - movb (p_ss_desc+4), dl - - mov ax, 8(bp) - mov dx, 10(bp) ! Kernel cs (absolute address) - mov (p_cs_desc+2), ax - movb (p_cs_desc+4), dl - - mov dx, cs ! Monitor cs - xor ax, ax ! dx:ax = Monitor code segment - call seg2abs - mov (p_mcs_desc+2), ax - movb (p_mcs_desc+4), dl - - push MCS_SELECTOR - push int86 ! Far address to INT86 support - - o32 push 20(bp) ! Address of a.out headers - - push 0 - push 18(bp) ! 32 bit size of parameters on stack - push 0 - push 16(bp) ! 32 bit address of parameters (ss relative) - - push MCS_SELECTOR - push ret386 ! Monitor far return address - - push 0 - push CS_SELECTOR - push 6(bp) - push 4(bp) ! 32 bit far address to kernel entry point - - call real2prot ! Switch to protected mode - mov ax, DS_SELECTOR - mov ds, ax ! Kernel data - mov ax, ES_SELECTOR - mov es, ax ! Flat 4 Gb - o32 retf ! Make a far call to the kernel - -! Minix-86 returns here on a halt or reboot. -ret86: - mov 8(bp), ax - mov 10(bp), dx ! Return value - jmp return - -! Minix-386 returns here on a halt or reboot. -ret386: - o32 mov 8(bp), eax ! Return value - call prot2real ! Switch to real mode - -return: - mov sp, bp ! Pop parameters - sti ! Can take interrupts again - - call _get_video ! MDA, CGA, EGA, ... - movb dh, 24 ! dh = row 24 - cmp ax, 2 ! At least EGA? - jb is25 ! Otherwise 25 rows - push ds - xor ax, ax ! Vector & BIOS data segments - mov ds, ax - movb dh, (0x0484) ! Number of rows on display minus one - pop ds -is25: - xorb dl, dl ! dl = column 0 - xorb bh, bh ! Page 0 - movb ah, 0x02 ! Set cursor position - int 0x10 - - xorb ah, ah ! Whack the disk system, Minix may have messed - movb dl, 0x80 ! it up - int 0x13 - - call gettrueproc - cmp ax, 286 - jb noclock - xorb al, al -tryclk: decb al - jz noclock - movb ah, 0x02 ! Get real-time clock time (from CMOS clock) - int 0x1A - jc tryclk ! Carry set, not running or being updated - movb al, ch ! ch = hour in BCD - call bcd ! al = (al >> 4) * 10 + (al & 0x0F) - mulb (c60) ! 60 minutes in an hour - mov bx, ax ! bx = hour * 60 - movb al, cl ! cl = minutes in BCD - call bcd - add bx, ax ! bx = hour * 60 + minutes - movb al, dh ! dh = seconds in BCD - call bcd - xchg ax, bx ! ax = hour * 60 + minutes, bx = seconds - mul (c60) ! dx-ax = (hour * 60 + minutes) * 60 - add bx, ax - adc dx, 0 ! dx-bx = seconds since midnight - mov ax, dx - mul (c19663) - xchg ax, bx - mul (c19663) - add dx, bx ! dx-ax = dx-bx * (0x1800B0 / (2*2*2*2*5)) - mov cx, ax ! (0x1800B0 = ticks per day of BIOS clock) - mov ax, dx - xor dx, dx - div (c1080) - xchg ax, cx - div (c1080) ! cx-ax = dx-ax / (24*60*60 / (2*2*2*2*5)) - mov dx, ax ! cx-dx = ticks since midnight - movb ah, 0x01 ! Set system time - int 0x1A -noclock: - - mov ax, 8(bp) - mov dx, 10(bp) ! dx-ax = return value from the kernel - pop bp - ret ! Return to monitor as if nothing much happened - -! Transform BCD number in al to a regular value in ax. -bcd: movb ah, al - shrb ah, 4 - andb al, 0x0F - aad ! ax = (al >> 4) * 10 + (al & 0x0F) - ret - -! Support function for Minix-386 to make an 8086 interrupt call. -int86: - mov bp, sp - call prot2real - - o32 xor eax, eax - mov es, ax ! Vector & BIOS data segments -o32 eseg mov (0x046C), eax ! Clear BIOS clock tick counter - - sti ! Enable interrupts - - movb al, 0xCD ! INT instruction - movb ah, 8(bp) ! Interrupt number? - testb ah, ah - jnz 0f ! Nonzero if INT, otherwise far call - push cs - push intret+2 ! Far return address - o32 push 12(bp) ! Far driver address - mov ax, 0x90CB ! RETF; NOP -0: cseg mov (intret), ax ! Patch 'INT n' or 'RETF; NOP' into code - - mov ds, 16(bp) ! Load parameters - mov es, 18(bp) - o32 mov eax, 20(bp) - o32 mov ebx, 24(bp) - o32 mov ecx, 28(bp) - o32 mov edx, 32(bp) - o32 mov esi, 36(bp) - o32 mov edi, 40(bp) - o32 mov ebp, 44(bp) - -intret: int 0xFF ! Do the interrupt or far call - - o32 push ebp ! Save results - o32 pushf - mov bp, sp - o32 pop 8+8(bp) ! eflags - mov 8+16(bp), ds - mov 8+18(bp), es - o32 mov 8+20(bp), eax - o32 mov 8+24(bp), ebx - o32 mov 8+28(bp), ecx - o32 mov 8+32(bp), edx - o32 mov 8+36(bp), esi - o32 mov 8+40(bp), edi - o32 pop 8+44(bp) ! ebp - - cli ! Disable interrupts - - xor ax, ax - mov ds, ax ! Vector & BIOS data segments - o32 mov cx, (0x046C) ! Collect lost clock ticks in ecx - - mov ax, ss - mov ds, ax ! Restore monitor ds - call real2prot - mov ax, DS_SELECTOR ! Kernel data - mov ds, ax - o32 retf ! Return to the kernel - -! Switch from real to protected mode. -real2prot: - movb ah, 0x02 ! Code for A20 enable - call gate_A20 - - lgdt (p_gdt_desc) ! Global descriptor table - o32 mov eax, (pdbr) ! Load page directory base register - mov cr3, eax - mov eax, cr0 - o32 xchg eax, (msw) ! Exchange real mode msw for protected mode msw - mov cr0, eax - jmpf MCS_SELECTOR:cs_prot ! Set code segment selector -cs_prot: - mov ax, SS_SELECTOR ! Set data selectors - mov ds, ax - mov es, ax - mov ss, ax - ret - -! Switch from protected to real mode. -prot2real: - lidt (p_idt_desc) ! Real mode interrupt vectors - mov eax, cr3 - o32 mov (pdbr), eax ! Save page directory base register - mov eax, cr0 - o32 xchg eax, (msw) ! Exchange protected mode msw for real mode msw - mov cr0, eax - jmpf 0xDEAD:cs_real ! Reload cs register -cs_real: - mov ax, 0xBEEF -ds_real: - mov ds, ax ! Reload data segment registers - mov es, ax - mov ss, ax - - xorb ah, ah ! Code for A20 disable - !jmp gate_A20 - -! Enable (ah = 0x02) or disable (ah = 0x00) the A20 address line. -gate_A20: - cmp (bus), 2 ! PS/2 bus? - je gate_PS_A20 - call kb_wait - movb al, 0xD1 ! Tell keyboard that a command is coming - outb 0x64 - call kb_wait - movb al, 0xDD ! 0xDD = A20 disable code if ah = 0x00 - orb al, ah ! 0xDF = A20 enable code if ah = 0x02 - outb 0x60 - call kb_wait - movb al, 0xFF ! Pulse output port - outb 0x64 - call kb_wait ! Wait for the A20 line to settle down - ret -kb_wait: - inb 0x64 - testb al, 0x02 ! Keyboard input buffer full? - jnz kb_wait ! If so, wait - ret - -gate_PS_A20: ! The PS/2 can twiddle A20 using port A - inb 0x92 ! Read port A - andb al, 0xFD - orb al, ah ! Set A20 bit to the required state - outb 0x92 ! Write port A - jmp .+2 ! Small delay -A20ok: inb 0x92 ! Check port A - andb al, 0x02 - cmpb al, ah ! A20 line settled down to the new state? - jne A20ok ! If not then wait - ret - -! void int15(bios_env_t *ep) -! Do an "INT 15" call, primarily for APM (Power Management). -.define _int15 -_int15: - push si ! Save callee-save register si - mov si, sp - mov si, 4(si) ! ep - mov ax, (si) ! ep->ax - mov bx, 2(si) ! ep->bx - mov cx, 4(si) ! ep->cx - int 0x15 ! INT 0x15 BIOS call - pushf ! Save flags - mov (si), ax ! ep->ax - mov 2(si), bx ! ep->bx - mov 4(si), cx ! ep->cx - pop 6(si) ! ep->flags - pop si ! Restore - ret - -! void scan_keyboard(void) -! Read keyboard character. Needs to be done in case one is waiting. -.define _scan_keyboard -_scan_keyboard: - movb ah, 1 ! Check keyboard - int 0x16 - jz no_key - movb ah, 0 ! Empty it - int 0x16 -no_key: ret - -.sect .rom - .align 4 -c60: .data2 60 ! Constants for MUL and DIV -c1024: .data2 1024 -c1080: .data2 1080 -c19663: .data2 19663 - -.sect .data - .align 4 - -! Global descriptor tables. - UNSET = 0 ! Must be computed - -! For "Extended Memory Block Move". -x_gdt: -x_null_desc: - ! Null descriptor - .data2 0x0000, 0x0000 - .data1 0x00, 0x00, 0x00, 0x00 -x_gdt_desc: - ! Descriptor for this descriptor table - .data2 6*8-1, UNSET - .data1 UNSET, 0x00, 0x00, 0x00 -x_src_desc: - ! Source segment descriptor - .data2 0xFFFF, UNSET - .data1 UNSET, 0x92, 0x00, 0x00 -x_dst_desc: - ! Destination segment descriptor - .data2 0xFFFF, UNSET - .data1 UNSET, 0x92, 0x00, 0x00 -x_bios_desc: - ! BIOS segment descriptor (scratch for int 0x15) - .data2 UNSET, UNSET - .data1 UNSET, UNSET, UNSET, UNSET -x_ss_desc: - ! BIOS stack segment descriptor (scratch for int 0x15) - .data2 UNSET, UNSET - .data1 UNSET, UNSET, UNSET, UNSET - -! Protected mode descriptor table. -p_gdt: -p_null_desc: - ! Null descriptor - .data2 0x0000, 0x0000 - .data1 0x00, 0x00, 0x00, 0x00 -p_gdt_desc: - ! Descriptor for this descriptor table - .data2 8*8-1, UNSET - .data1 UNSET, 0x00, 0x00, 0x00 -p_idt_desc: - ! Real mode interrupt descriptor table descriptor - .data2 0x03FF, 0x0000 - .data1 0x00, 0x00, 0x00, 0x00 -p_ds_desc: - ! Kernel data segment descriptor (4Gb flat) - .data2 0xFFFF, UNSET - .data1 UNSET, 0x92, 0xCF, 0x00 -p_es_desc: - ! Physical memory descriptor (4Gb flat) - .data2 0xFFFF, 0x0000 - .data1 0x00, 0x92, 0xCF, 0x00 -p_ss_desc: - ! Monitor data segment descriptor (64Kb flat) - .data2 0xFFFF, UNSET - .data1 UNSET, 0x92, 0x00, 0x00 -p_cs_desc: - ! Kernel code segment descriptor (4Gb flat) - .data2 0xFFFF, UNSET - .data1 UNSET, 0x9A, 0xCF, 0x00 -p_mcs_desc: - ! Monitor code segment descriptor (64 kb flat) (unused) - .data2 0xFFFF, UNSET - .data1 UNSET, 0x9A, 0x00, 0x00 - -xms_handle: .data2 -1 ! Handle of allocated XMS block -vfd: .data2 -1 ! Virtual disk file handle - -.sect .bss - .comm xms_driver, 4 ! Vector to XMS driver - .comm old_vid_mode, 2 ! Video mode at startup - .comm cur_vid_mode, 2 ! Current video mode - .comm msw, 4 ! Saved machine status word (cr0) - .comm pdbr, 4 ! Saved page directory base register (cr3) - .comm escape, 2 ! Escape typed? - .comm bus, 2 ! Saved return value of _get_bus - .comm unchar, 2 ! Char returned by ungetch(c) - -! -! $PchId: doshead.ack.s,v 1.7 2002/02/27 19:37:52 philip Exp $ diff --git a/boot/edparams/Makefile b/boot/edparams/Makefile new file mode 100644 index 000000000..2cb773093 --- /dev/null +++ b/boot/edparams/Makefile @@ -0,0 +1,12 @@ +# edparams: customize boot; runs on both installer's and user's machines + +PROG= edparams +BINDIR= /usr/bin + +SRCS= boot.c rawfs.c +.PATH: ${.CURDIR}/../boot ${.CURDIR}/.. +CPPFLAGS= -DUNIX -I${MINIXSRCDIR} -I${.CURDIR}/.. + +MAN= # monitor.8 + +.include diff --git a/boot/installboot/Makefile b/boot/installboot/Makefile new file mode 100644 index 000000000..4454e8d16 --- /dev/null +++ b/boot/installboot/Makefile @@ -0,0 +1,12 @@ +# installboot: install the boot package; runs on the installer's machine + +PROG= installboot +BINDIR= /usr/bin + +SRCS= installboot.c rawfs.c +.PATH: ${.CURDIR}/.. +CPPFLAGS= -I${MINIXSRCDIR} -I${.CURDIR}/.. + +MAN= # installboot.8 + +.include diff --git a/boot/installboot.c b/boot/installboot/installboot.c similarity index 100% rename from boot/installboot.c rename to boot/installboot/installboot.c diff --git a/boot/jumpboot/Makefile b/boot/jumpboot/Makefile new file mode 100644 index 000000000..d8d88f54e --- /dev/null +++ b/boot/jumpboot/Makefile @@ -0,0 +1,19 @@ +# jumpboot: supplementary MBR code (alternate to masterboot) + +.include + +# XXX: Can only be built with ACK currently +.include "${MINIXSRCDIR}/boot/minix.ack16.mk" +AFLAGS+= -Was-ncc +STRIPFLAG= -s + +PROG= jumpboot + +SRCS= jumpboot.s + +BINDIR= /usr/mdec +MAN= + +LIBC= # defined, to silence bsd.*.mk + +.include diff --git a/boot/jumpboot.s b/boot/jumpboot/jumpboot.s similarity index 100% rename from boot/jumpboot.s rename to boot/jumpboot/jumpboot.s diff --git a/boot/masterboot/Makefile b/boot/masterboot/Makefile new file mode 100644 index 000000000..f95384626 --- /dev/null +++ b/boot/masterboot/Makefile @@ -0,0 +1,20 @@ +# masterboot: MBR code, first to run, 16-bit mode + +.include + +# XXX: Can only be built with ACK currently +.include "${MINIXSRCDIR}/boot/minix.ack16.mk" +AFLAGS+= -Was-ncc +STRIPFLAG= -s + + +PROG= masterboot + +SRCS= masterboot.s + +BINDIR= /usr/mdec +MAN= + +LIBC= # defined, to silence bsd.*.mk + +.include diff --git a/boot/masterboot.s b/boot/masterboot/masterboot.s similarity index 100% rename from boot/masterboot.s rename to boot/masterboot/masterboot.s diff --git a/boot/minix.ack16.mk b/boot/minix.ack16.mk new file mode 100644 index 000000000..f069894a5 --- /dev/null +++ b/boot/minix.ack16.mk @@ -0,0 +1,11 @@ +# Makefile fragment to use Ack compiler (16-bit i86 target) +ARCH= i86 +LIBDIR= /usr/lib/i86 # force + +CC:=${CC:C/.*[gp]cc/cc/:C/clang/cc/} +AR=aal +COMPILER_TYPE=ack +OBJECT_FMT=a.out +CPPFLAGS+= -mi86 +AFLAGS+= -mi86 +LDFLAGS+= -mi86 -.o -com # no crtso, common I+D diff --git a/boot/mkfhead.s b/boot/mkfhead.s deleted file mode 100644 index 221e1faea..000000000 --- a/boot/mkfhead.s +++ /dev/null @@ -1,137 +0,0 @@ -! Mkfhead.s - DOS & BIOS support for mkfile.c Author: Kees J. Bot -! 9 May 1998 -! -! This file contains the startup and low level support for the MKFILE.COM -! utility. See doshead.ack.s for more comments on .COM files. -! -.sect .text; .sect .rom; .sect .data; .sect .bss -.sect .text - -.define _PSP -_PSP: - .space 256 ! Program Segment Prefix - -mkfile: - cld ! C compiler wants UP - xor ax, ax ! Zero - mov di, _edata ! Start of bss is at end of data - mov cx, _end ! End of bss (begin of heap) - sub cx, di ! Number of bss bytes - shr cx, 1 ! Number of words - rep stos ! Clear bss - - xor cx, cx ! cx = argc - xor bx, bx - push bx ! argv[argc] = NULL - movb bl, (_PSP+0x80) ! Argument byte count -0: movb _PSP+0x81(bx), ch ! Null terminate - dec bx - js 9f - cmpb _PSP+0x81(bx), 0x20 ! Whitespace? - jbe 0b -1: dec bx ! One argument character - js 2f - cmpb _PSP+0x81(bx), 0x20 ! More argument characters? - ja 1b -2: lea ax, _PSP+0x81+1(bx) ! Address of argument - push ax ! argv[n] - inc cx ! argc++; - test bx, bx - jns 0b ! More arguments? -9: movb _PSP+0x81(bx), ch ! Make a null string - lea ax, _PSP+0x81(bx) - push ax ! to use as argv[0] - inc cx ! Final value of argc - mov ax, sp - push ax ! argv - push cx ! argc - call _main ! main(argc, argv) - push ax - call _exit ! exit(main(argc, argv)) - -! int creat(const char *path, mode_t mode) -! Create a file with the old creat() call. -.define _creat -_creat: - mov bx, sp - mov dx, 2(bx) ! Filename - xor cx, cx ! Ignore mode, always read-write - movb ah, 0x3C ! "CREAT" -dos: int 0x21 ! ax = creat(path, 0666); - jc seterrno - ret - -seterrno: - mov (_errno), ax ! Set errno to the DOS error code - mov ax, -1 - cwd ! return -1L; - ret - -! int open(const char *path, int oflag) -! Open a file with the oldfashioned two-argument open() call. -.define _open -_open: - mov bx, sp - mov dx, 2(bx) ! Filename - movb al, 4(bx) ! O_RDONLY, O_WRONLY, O_RDWR - movb ah, 0x3D ! "OPEN" - jmp dos - -! int close(int fd) -! Close an open file. -.define _close -_close: - mov bx, sp - mov bx, 2(bx) ! bx = file handle - movb ah, 0x3E ! "CLOSE" - jmp dos - -! void exit(int status) -! void _exit(int status) -! Return to DOS. -.define _exit, __exit, ___exit -_exit: -__exit: -___exit: - pop ax - pop ax ! al = status - movb ah, 0x4C ! "EXIT" - int 0x21 - hlt - -! ssize_t read(int fd, void *buf, size_t n) -! Read bytes from an open file. -.define _read -_read: - mov bx, sp - mov cx, 6(bx) - mov dx, 4(bx) - mov bx, 2(bx) - movb ah, 0x3F ! "READ" - jmp dos - -! ssize_t write(int fd, const void *buf, size_t n) -! Write bytes to an open file. -.define _write -_write: - mov bx, sp - mov cx, 6(bx) - mov dx, 4(bx) - mov bx, 2(bx) - movb ah, 0x40 ! "WRITE" - jmp dos - -! off_t lseek(int fd, off_t offset, int whence) -! Set file position for read or write. -.define _lseek -_lseek: - mov bx, sp - movb al, 8(bx) ! SEEK_SET, SEEK_CUR, SEEK_END - mov dx, 4(bx) - mov cx, 6(bx) ! cx:dx = offset - mov bx, 2(bx) - movb ah, 0x42 ! "LSEEK" - jmp dos - -! -! $PchId: mkfhead.ack.s,v 1.3 1999/01/14 21:17:06 philip Exp $ diff --git a/boot/mkfile.c b/boot/mkfile.c deleted file mode 100644 index d9a130d54..000000000 --- a/boot/mkfile.c +++ /dev/null @@ -1,179 +0,0 @@ -/* mkfile 1.0 - create a file under DOS for use as a Minix "disk". - * Author: Kees J. Bot - * 9 May 1998 - */ -#define nil 0 -#include -#include -#include - -/* Stuff normally found in , , etc. */ -extern int errno; -int creat(const char *file, int mode); -int open(const char *file, int oflag); -off_t lseek(int fd, off_t offset, int whence); -ssize_t write(int fd, const char *buf, size_t len); -void exit(int status); -int printf(const char *fmt, ...); - -#define O_WRONLY 1 -#define SEEK_SET 0 -#define SEEK_END 2 - -/* Kernel printf requires a putk() function. */ -void putk(int c) -{ - char ch = c; - - if (c == 0) return; - if (c == '\n') putk('\r'); - (void) write(2, &ch, 1); -} - -static void usage(void) -{ - printf("Usage: mkfile [gmk] \n" - "(Example sizes, all 50 meg: 52428800, 51200k, 50m)\n"); - exit(1); -} - -char *strerror(int err) -/* Translate some DOS error numbers to text. */ -{ - static struct errlist { - int err; - char *what; - } errlist[] = { - { 0, "No error" }, - { 1, "Function number invalid" }, - { 2, "File not found" }, - { 3, "Path not found" }, - { 4, "Too many open files" }, - { 5, "Access denied" }, - { 6, "Invalid handle" }, - { 12, "Access code invalid" }, - { 39, "Insufficient disk space" }, - }; - struct errlist *ep; - static char unknown[]= "Error 65535"; - unsigned e; - char *p; - - for (ep= errlist; ep < errlist + sizeof(errlist)/sizeof(errlist[0]); - ep++) { - if (ep->err == err) return ep->what; - } - p= unknown + sizeof(unknown) - 1; - e= err; - do *--p= '0' + (e % 10); while ((e /= 10) > 0); - strcpy(unknown + 6, p); - return unknown; -} - -int main(int argc, char **argv) -{ - static char buf[512]; - unsigned long size, mul; - off_t offset; - char *cp; - int fd; - char *file; - - if (argc != 3) usage(); - - cp= argv[1]; - size= 0; - while ((unsigned) (*cp - '0') < 10) { - unsigned d= *cp++ - '0'; - if (size <= (ULONG_MAX-9) / 10) { - size= size * 10 + d; - } else { - size= ULONG_MAX; - } - } - if (cp == argv[1]) usage(); - while (*cp != 0) { - mul = 1; - switch (*cp++) { - case 'G': - case 'g': mul *= 1024; - case 'M': - case 'm': mul *= 1024; - case 'K': - case 'k': mul *= 1024; - case 'B': - case 'b': break; - default: usage(); - } - if (size <= ULONG_MAX / mul) { - size *= mul; - } else { - size= ULONG_MAX; - } - } - - if (size > 1024L*1024*1024) { - printf("mkfile: A file size over 1G is a bit too much\n"); - exit(1); - } - - /* Open existing file, or create a new file. */ - file= argv[2]; - if ((fd= open(file, O_WRONLY)) < 0) { - if (errno == 2) { - fd= creat(file, 0666); - } - } - if (fd < 0) { - printf("mkfile: Can't open %s: %s\n", file, strerror(errno)); - exit(1); - } - - /* How big is the file now? */ - if ((offset= lseek(fd, 0, SEEK_END)) == -1) { - printf("mkfile: Can't seek in %s: %s\n", file, strerror(errno)); - exit(1); - } - - if (offset == 0 && size == 0) exit(0); /* Huh? */ - - /* Write the first bit if the file is zero length. This is necessary - * to circumvent a DOS bug by extending a new file by lseek. We also - * want to make sure there are zeros in the first sector. - */ - if (offset == 0) { - if (write(fd, buf, sizeof(buf)) == -1) { - printf("mkfile: Can't write to %s: %s\n", - file, strerror(errno)); - exit(1); - } - } - - /* Seek to the required size and write 0 bytes to extend/truncate the - * file to that size. - */ - if (lseek(fd, size, SEEK_SET) == -1) { - printf("mkfile: Can't seek in %s: %s\n", file, strerror(errno)); - exit(1); - } - if (write(fd, buf, 0) == -1) { - printf("mkfile: Can't write to %s: %s\n", - file, strerror(errno)); - exit(1); - } - - /* Did the file become the required size? */ - if ((offset= lseek(fd, 0, SEEK_END)) == -1) { - printf("mkfile: Can't seek in %s: %s\n", file, strerror(errno)); - exit(1); - } - if (offset != size) { - printf("mkfile: Failed to extend %s. Disk full?\n", file); - exit(1); - } - return 0; -} - -/* - * $PchId: mkfile.c,v 1.4 2000/08/13 22:06:40 philip Exp $ - */ diff --git a/boot/updateboot.sh b/boot/updateboot.sh index 0a4132c54..11234e962 100755 --- a/boot/updateboot.sh +++ b/boot/updateboot.sh @@ -1,6 +1,7 @@ #!/bin/sh set -e +MDEC=/usr/mdec BOOT=/boot/boot ROOT=`printroot -r` @@ -20,8 +21,8 @@ fi make install || true echo Installing boot monitor into $BOOT. -cp boot $BOOT +cp $MDEC/boot $BOOT echo Patching position of $BOOT into $ROOT. -installboot -d "$ROOT" /usr/mdec/bootblock $BOOT +installboot -d "$ROOT" $MDEC/bootblock $BOOT sync diff --git a/tools/chrootmake.sh b/tools/chrootmake.sh index c030dc059..8a4e59764 100755 --- a/tools/chrootmake.sh +++ b/tools/chrootmake.sh @@ -14,7 +14,7 @@ rm revision rm /boot/image/* make install cp /boot/image/* /boot/image_big # Make big image accessible by this name -cp ../boot/boot /boot/boot +cp ../boot/boot/boot /boot/boot cd /usr/src if [ $MAKEMAP -ne 0 ]; then find . -type f -perm 755 | xargs nm -n 2> /dev/null > symbols.txt diff --git a/tools/release.sh b/tools/release.sh index e7c6b6b5a..1405c19c9 100755 --- a/tools/release.sh +++ b/tools/release.sh @@ -167,7 +167,7 @@ RELEASEDIR=/usr/r-staging RELEASEMNTDIR=/usr/r RELEASEPACKAGE=${RELEASEDIR}/usr/install/packages -IMAGE=../boot/cdbootblock +IMAGE=../boot/cdbootblock/cdbootblock ROOTIMAGE=rootimage CDFILES=/usr/tmp/cdreleasefiles sh tell_config OS_RELEASE . OS_VERSION >/tmp/rel.$$ @@ -528,7 +528,7 @@ fi if [ "$USB" -ne 0 ]; then mv $bootimage $IMG else - cp ../boot/boot $CDFILES + cp ../boot/boot/boot $CDFILES writeisofs -s0x0 -l MINIX -a boot -b $bootimage $boottype $CDFILES $IMG || exit 1 if [ "$HDEMU" -eq 0 ]