kjh@pollux.usc.edu (Kenneth J. Hendrickson) (07/27/90)
I have made the following changes/improvements/bug fixes to Minix: Bug Fixes: + Corrected handling of colour, bold, underlined, blinking, and reverse video Screen Attributes (console.c). I hope these make it into the next release of Minix. Improvements: + Separate bootblok.s files for each drive type. Now booting up won't beat your drive to death, trying to accommodate all drive types. Booting is also faster. + Put the screen into 43-line mode if EGA (or VGA) (start.x) I really liked the 43-line mode under DOS, and I like it under Minix also. Don't forget to modify your /etc/termcap file. + Put the screen into green/black if colour (start.x & console.s) If green/black isn't your favourite colours, then you can change the VIDATT parameter. Documentation is included. I hope these make it into the next release of Minix. Changes: + Use ^C for the SIGINT character instead of DEL + Use ^U for the SIGKILL character instead of @ + Erase the line on SIGKILL character, like on BSD This is more of a "religious" issue, like Andy says in his book. Still, I hope the SIGKILL stuff makes it into the next release. Ken Hendrickson N8DGN/6 kjh@usc.edu ...!uunet!usc!pollux!kjh #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. # Wrapped by kjh@pollux.usc.edu on Fri Jul 27 03:57:21 1990 echo x - /usr/src/local/kernel/Makefile.cdif sed '/^X/s///' > /usr/src/local/kernel/Makefile.cdif << '/' X*** /usr/src/minix/kernel/Makefile Fri Jul 20 01:19:10 1990 X--- Makefile Fri Jul 27 02:38:16 1990 X*************** X*** 3,13 **** X # The following nonstandard flags are used: X # -F: run cpp and cem sequentially (used when memory is tight) X # -T.: put temporaries in working directory (when RAM disk is small) X! BIN =. X! CC =cc X! CFLAGS =-F -T. X! CPP =/usr/lib/cpp X! CPPFLAGS =-DASLD -P X END =/usr/lib/end.s X LD =asld X LDFLAGS =-i X--- 3,14 ---- X # The following nonstandard flags are used: X # -F: run cpp and cem sequentially (used when memory is tight) X # -T.: put temporaries in working directory (when RAM disk is small) X! # -DEGA43 use 43-line mode on EGA (and VGA) displays X! BIN =. X! CC =cc X! CFLAGS =-F -T. -DEGA43 X! CPP =/usr/lib/cpp X! CPPFLAGS =-DASLD -P -DEGA43 X END =/usr/lib/end.s X LD =asld X LDFLAGS =-i / echo x - /usr/src/local/kernel/console.c.cdif sed '/^X/s///' > /usr/src/local/kernel/console.c.cdif << '/' X*** /usr/src/minix/kernel/console.c Fri Jul 20 01:19:12 1990 X--- console.c Thu Jul 26 22:12:50 1990 X*************** X*** 12,20 **** X #define M_VID_MASK 0x0FFF /* mask for 4K video RAM */ X #define C_RETRACE 0x0300 /* how many characters to display at once */ X #define M_RETRACE 0x7000 /* how many characters to display at once */ X! #define BLANK 0x0700 /* determines cursor color on blank screen */ X! #define LINE_WIDTH 80 /* # characters on a line */ X! #define SCR_LINES 25 /* # lines on the screen */ X #define SCR_BYTES 8000 /* size video RAM. multiple of 2*LINE_WIDTH */ X #define GO_FORWARD 0 /* scroll forward */ X #define GO_BACKWARD 1 /* scroll backward */ X--- 12,37 ---- X #define M_VID_MASK 0x0FFF /* mask for 4K video RAM */ X #define C_RETRACE 0x0300 /* how many characters to display at once */ X #define M_RETRACE 0x7000 /* how many characters to display at once */ X! X! #define BLANK 0x0200 /* determines cursor color on blank screen */ X! /* Bit 14 (0x400) is for background Red X! * Bit 13 (0x200) is for background Green X! * Bit 12 (0x100) is for background Blue X! * Bit 10 (0x400) is for foreground Red X! * Bit 9 (0x200) is for foreground Green X! * Bit 8 (0x100) is for foreground Blue X! * It is probably unwise to set bits 15 or 11 of BLANK. X! * Bit 15 (0x8000) is for foreground blinking X! * Bit 11 (0x0800) is for foreground intensity X! */ X! X! #define LINE_WIDTH 80 /* # characters on a line */ X! #ifdef EGA43 X! #define SCR_LINES 43 /* # lines on the screen */ X! #else X! #define SCR_LINES 25 /* # lines on the screen */ X! #endif X! X #define SCR_BYTES 8000 /* size video RAM. multiple of 2*LINE_WIDTH */ X #define GO_FORWARD 0 /* scroll forward */ X #define GO_BACKWARD 1 /* scroll backward */ X*************** X*** 36,42 **** X /* Global variables used by the console driver. */ X PUBLIC int vid_mask; /* 037777 for color (16K) or 07777 for mono */ X PUBLIC int vid_port; /* I/O port for accessing 6845 */ X! PUBLIC int blank_color = 0x0700; /* display code for blank */ X X /* Private variables used by the console driver. */ X PRIVATE vid_retrace; /* how many characters to display per burst */ X--- 53,59 ---- X /* Global variables used by the console driver. */ X PUBLIC int vid_mask; /* 037777 for color (16K) or 07777 for mono */ X PUBLIC int vid_port; /* I/O port for accessing 6845 */ X! PUBLIC int blank_color = BLANK; /* display code for blank */ X X /* Private variables used by the console driver. */ X PRIVATE vid_retrace; /* how many characters to display per burst */ X*************** X*** 348,354 **** X * ESC [nM deletes n lines at cursor X * ESC [nP deletes n chars at cursor X * ESC [n@ inserts n chars at cursor X! * ESC [nm enables rendition n (0=normal, 4=bold, 5=blinking, 7=reverse) X * ESC M scrolls the screen backwards if the cursor is on the top line X */ X X--- 365,372 ---- X * ESC [nM deletes n lines at cursor X * ESC [nP deletes n chars at cursor X * ESC [n@ inserts n chars at cursor X! * ESC [nm enables rendition n X! (0=normal, 1=bold, 4=underlined, 5=blinking, 7=reverse) X * ESC M scrolls the screen backwards if the cursor is on the top line X */ X X*************** X*** 529,564 **** X case 'm': /* ESC [nm enables rendition n */ X switch (value) { X case 1: /* BOLD */ X! if (color) X! one_con_attribute = /* red fg */ X! (attr & 0xf0ff) | 0x0400; X! else X! one_con_attribute |= 0x0800; /* inten*/ X break; X X case 4: /* UNDERLINE */ X if (color) X! one_con_attribute = /* blue fg */ X! (attr & 0xf0ff) | 0x0100; X else X one_con_attribute = /* ul */ X (attr & 0x8900); X break; X X case 5: /* BLINKING */ X! if (color) /* can't blink color */ X! one_con_attribute = /* magenta fg */ X! (attr & 0xf0ff) | 0x0500; X! else X! one_con_attribute |= /* blink */ X! 0x8000; X break; X X case 7: /* REVERSE (black on light grey) */ X if (color) X one_con_attribute = X! ((attr & 0xf000) >> 4) | X! ((attr & 0x0f00) << 4); X else if ((attr & 0x7000) == 0) X one_con_attribute = X (attr & 0x8800) | 0x7000; X--- 547,584 ---- X case 'm': /* ESC [nm enables rendition n */ X switch (value) { X case 1: /* BOLD */ X! one_con_attribute |= 0x0800; /* inten */ X break; X X case 4: /* UNDERLINE */ X if (color) X! if ((attr & 0x6000) == 0) X! /* cyan on [black|blue] bg X! * This is not standard, X! * but it is easier to see. X! */ X! one_con_attribute = X! (attr & 0xf8ff) | 0x0300; X! else X! /* blue on other bg */ X! one_con_attribute = X! (attr & 0xf8ff) | 0x0100; X else X one_con_attribute = /* ul */ X (attr & 0x8900); X break; X X case 5: /* BLINKING */ X! /* EGA, CGA, and MONO can all blink */ X! one_con_attribute |= 0x8000; /* blink */ X break; X X case 7: /* REVERSE (black on light grey) */ X if (color) X one_con_attribute = X! ((attr & 0x7000) >> 4) | X! ((attr & 0x0700) << 4) | X! (attr & 0x8800); X else if ((attr & 0x7000) == 0) X one_con_attribute = X (attr & 0x8800) | 0x7000; X*************** X*** 569,585 **** X X default: if (value >= 30 && value <= 37) { X one_con_attribute = X! (attr & 0xf0ff) | X! (ansi_colors[(value - 30)] << 8); X! blank_color = X! (blank_color & 0xf0ff) | X (ansi_colors[(value - 30)] << 8); X } else if (value >= 40 && value <= 47) { X one_con_attribute = X! (attr & 0x0fff) | X! (ansi_colors[(value - 40)] << 12); X! blank_color = X! (blank_color & 0x0fff) | X (ansi_colors[(value - 40)] << 12); X } else X one_con_attribute = blank_color; X--- 589,605 ---- X X default: if (value >= 30 && value <= 37) { X one_con_attribute = X! (attr & 0xf8ff) | X! (ansi_colors[(value - 30)] << 8); X! blank_color = X! (blank_color & 0xf8ff) | X (ansi_colors[(value - 30)] << 8); X } else if (value >= 40 && value <= 47) { X one_con_attribute = X! (attr & 0x8fff) | X! (ansi_colors[(value - 40)] << 12); X! blank_color = X! (blank_color & 0x8fff) | X (ansi_colors[(value - 40)] << 12); X } else X one_con_attribute = blank_color; X*************** X*** 768,774 **** X vid_retrace = C_VID_MASK + 1; X } X X! set_6845(CUR_SIZE, CURSOR_SHAPE); /* set cursor shape */ X set_6845(VID_ORG, 0); /* use page 0 of video ram */ X move_to(&tty_struct[0], 0, SCR_LINES-1); /* move cursor to lower left */ X } X--- 788,796 ---- X vid_retrace = C_VID_MASK + 1; X } X X! #ifndef LINE_CURSOR X! set_6845(CUR_SIZE, CURSOR_SHAPE); /* set cursor shape (block) */ X! #endif X set_6845(VID_ORG, 0); /* use page 0 of video ram */ X move_to(&tty_struct[0], 0, SCR_LINES-1); /* move cursor to lower left */ X } / echo x - /usr/src/local/kernel/start.x.cdif sed '/^X/s///' > /usr/src/local/kernel/start.x.cdif << '/' X*** /usr/src/minix/kernel/start.x Fri Jul 20 01:19:24 1990 X--- start.x Thu Jul 26 06:24:56 1990 X*************** X*** 50,57 **** X #define SET_PROTECT_VEC 0x15 /* set protected mode */ X # define SET_PROTECT_FUNC 0x89 X #define VIDEO 0x10 X! # define ALTERNATE_SELECT 0x12 X! # define A_S_INFO 0x10 X X .text X |*===========================================================================* X--- 50,75 ---- X #define SET_PROTECT_VEC 0x15 /* set protected mode */ X # define SET_PROTECT_FUNC 0x89 X #define VIDEO 0x10 X! # define ALTERNATE_SELECT 0x12 /* alternate select (Prt-Sc) */ X! # define A_S_INFO 0x10 X! # define SET_VID_MOD 0x00 /* set video mode function */ X! # define TEXT80 0x03 /* 80x25 16-colour text mode */ X! # define CHAR_GEN 0x11 /* character generator interface */ X! # define LOAD_8x8 0x12 /* load the ROM BIOS 8x8 char set */ X! # define CRTC_PORT 0x3d4 /* CRTC address for colour (EGA) */ X! # define CUR_SVAL 0x06 /* cursor start value (underscore) */ X! # define CUR_EVAL 0x00 /* cursor end value (underscore) */ X! # define CUR_SREG 0x0a /* cursor start register number */ X! # define CUR_EREG 0x0b /* cursor end register number */ X! # define PRT_SC 0x20 /* select alternate Prt-Sc routine */ X! # define SCRL_WINUP 0x06 /* scroll window up function */ X! # define VIDATT 0x02 /* video attributes green/black */ X! # define LINE_WIDTH 80 /* number of characters per line */ X! # ifdef EGA43 X! # define SCR_LINES 43 /* number of lines on the screen */ X! # else X! # define SCR_LINES 25 /* number of lines on the screen */ X! # endif X X .text X |*===========================================================================* X*************** X*** 174,179 **** X--- 192,243 ---- X movb al,bl | success is determined by knowing X movb ah,#0 | a successful call will change bl X sub ax,#A_S_INFO | nonzero means it is EGA X+ push ax | save correct return value X+ X+ #ifdef EGA43 X+ jz no_43 | non-EGA can't do 43-line mode X+ X+ | If the display is an EGA (or VGA), X+ | Then establish 43-line mode. X+ | We have to do this now, as we can't do it in protected mode. X+ X+ movb ah,#SET_VID_MOD | set video mode function X+ movb al,#TEXT80 | 80x25 16-colour text mode X+ int VIDEO X+ X+ movb ah,#CHAR_GEN | character generator interface function X+ movb al,#LOAD_8x8 | load the ROM BIOS 8x8 character set X+ movb bl,#0 | bl = block to load X+ int VIDEO | load 8x8 characters into RAM X+ X+ | set up for underscore cursor X+ | console.c code will change to block cursor X+ | unless disabled by compiling with X+ | -DLINE_CURSOR X+ mov dx,#CRTC_PORT | CRTC address port for colour X+ movb ah,#CUR_SVAL | cursor start value X+ movb al,#CUR_SREG | cursor start register number X+ outw | update CRTC Cursor Start register X+ movb ah,#CUR_EVAL | cursor end value X+ movb al,#CUR_EREG | cursor end register number X+ outw | update CRTC Cursor End register X+ X+ movb ah,#ALTERNATE_SELECT | alternate select function X+ movb bl,#PRT_SC | use alternate video BIOS Prt-Sc routine X+ int VIDEO | update INT 5 vector (print screen) X+ #endif X+ X+ no_43: X+ | Use scroll window to clear screen X+ movb ah,#SCRL_WINUP | scroll window up X+ movb al,#0 | number of lines to scroll X+ movb bh,#VIDATT | and set the video attributes X+ xor cx,cx X+ movb dh,#SCR_LINES-1 | number of lines on the screen X+ movb dl,#LINE_WIDTH-1 | number of characters per line X+ int VIDEO X+ X+ pop ax | pass correct return value X ret X X / echo x - /usr/src/local/kernel/tty.c.cdif sed '/^X/s///' > /usr/src/local/kernel/tty.c.cdif << '/' X*** /usr/src/minix/kernel/tty.c Fri Jul 20 01:19:27 1990 X--- tty.c Mon Jul 23 03:52:35 1990 X*************** X*** 281,289 **** X X /* Now do kill processing (remove current line). */ X if (ch == tp->tty_kill && tp->tty_escaped == NOT_ESCAPED) { X! while(chuck(tp) == OK) /* keep looping */ ; X! echo(tp, tp->tty_kill); X! echo(tp, '\n'); X return; X } X X--- 281,291 ---- X X /* Now do kill processing (remove current line). */ X if (ch == tp->tty_kill && tp->tty_escaped == NOT_ESCAPED) { X! while(chuck(tp) == OK) X! /* keep looping */ X! back_over(tp); X! /* echo(tp, tp->tty_kill); */ X! /* echo(tp, '\n'); */ X return; X } X / echo x - /usr/src/local/kernel/tty.h.cdif sed '/^X/s///' > /usr/src/local/kernel/tty.h.cdif << '/' X*** /usr/src/minix/kernel/tty.h Fri Jul 20 01:19:27 1990 X--- tty.h Mon Jul 23 03:43:20 1990 X*************** X*** 9,17 **** X #define MAX_ESC_PARMS 2 /* number of escape sequence params allowed */ X X #define ERASE_CHAR '\b' /* default erase character */ X! #define KILL_CHAR '@' /* default kill character */ X! #define INTR_CHAR (char)0177 /* default interrupt character */ X! #define QUIT_CHAR (char) 034 /* default quit character */ X #define XOFF_CHAR (char) 023 /* default x-off character (CTRL-S) */ X #define XON_CHAR (char) 021 /* default x-on character (CTRL-Q) */ X #define EOT_CHAR (char) 004 /* CTRL-D */ X--- 9,17 ---- X #define MAX_ESC_PARMS 2 /* number of escape sequence params allowed */ X X #define ERASE_CHAR '\b' /* default erase character */ X! #define KILL_CHAR 025 /* default kill character ^U (was '@') */ X! #define INTR_CHAR 003 /* default interrupt character ^C (was 0177) */ X! #define QUIT_CHAR (char) 034 /* default quit character ^\ */ X #define XOFF_CHAR (char) 023 /* default x-off character (CTRL-S) */ X #define XON_CHAR (char) 021 /* default x-on character (CTRL-Q) */ X #define EOT_CHAR (char) 004 /* CTRL-D */ X*************** X*** 75,82 **** X X /* User settable characters: erase, kill, interrupt, quit, x-on; x-off. */ X char tty_erase; /* char used to erase 1 char (init ^H) */ X! char tty_kill; /* char used to erase a line (init @) */ X! char tty_intr; /* char used to send SIGINT (init DEL) */ X char tty_quit; /* char used for core dump (init CTRL-\) */ X char tty_xon; /* char used to start output (init CTRL-Q)*/ X char tty_xoff; /* char used to stop output (init CTRL-S) */ X--- 75,82 ---- X X /* User settable characters: erase, kill, interrupt, quit, x-on; x-off. */ X char tty_erase; /* char used to erase 1 char (init ^H) */ X! char tty_kill; /* char used to erase a line (init ^U was @) */ X! char tty_intr; /* char used to send SIGINT (init ^C was DEL) */ X char tty_quit; /* char used for core dump (init CTRL-\) */ X char tty_xon; /* char used to start output (init CTRL-Q)*/ X char tty_xoff; /* char used to stop output (init CTRL-S) */ / echo x - /usr/src/local/commands/stty.c.cdif sed '/^X/s///' > /usr/src/local/commands/stty.c.cdif << '/' X*** /usr/src/minix/commands/stty.c Fri Jul 20 00:15:35 1990 X--- stty.c Mon Jul 23 03:17:56 1990 X*************** X*** 12,18 **** X #define STOPC 023 /* CTRL-S */ X #define QUITC 034 /* CTRL-\ */ X #define EOFC 004 /* CTRL-D */ X! #define DELC 0177 /* DEL */ X #define BYTE 0377 X #define FD 0 /* which file descriptor to use */ X X--- 12,19 ---- X #define STOPC 023 /* CTRL-S */ X #define QUITC 034 /* CTRL-\ */ X #define EOFC 004 /* CTRL-D */ X! #define DELC 003 /* CTRL-C */ /* 0177 DEL */ X! #define KILLC 025 /* CTRL-U */ /* '@' */ X #define BYTE 0377 X #define FD 0 /* which file descriptor to use */ X X*************** X*** 262,268 **** X args.sg_flags = ECHO | CRMOD | XTABS | BITS8; X args.sg_ispeed = B1200; X args.sg_ospeed = B1200; X! args.sg_kill = '@'; X args.sg_erase = '\b'; X tch.t_intrc = DELC; X tch.t_quitc = QUITC; X--- 263,269 ---- X args.sg_flags = ECHO | CRMOD | XTABS | BITS8; X args.sg_ispeed = B1200; X args.sg_ospeed = B1200; X! args.sg_kill = KILLC; X args.sg_erase = '\b'; X tch.t_intrc = DELC; X tch.t_quitc = QUITC; / echo x - /usr/src/local/tools/bootblok1200.s sed '/^X/s///' > /usr/src/local/tools/bootblok1200.s << '/' X| When the PC is powered on, it reads the first block from the floppy X| disk into address 0x7C00 and jumps to it. This boot block must contain X| the boot program in this file. The boot program first copies itself to X| address 256K - 1536 (to get itself out of the way). Then it loads the X| operating system from the boot diskette into memory, and then jumps to menu. X| Loading is not trivial because the PC is unable to read a track into X| memory across a 64K boundary, so the positioning of everything is critical. X| The number of sectors to load is contained at address 504 of this block. X| The value is put there by the build program after it has discovered how X| big the operating system is. When the bootblok program is finished loading, X| it jumps indirectly to the program (menu) which address is given by the X| last two words in the boot block. X| X| Summary of the words patched into the boot block by build: X| Word at 504: # sectors to load X| Word at 506: # DS value for menu X| Word at 508: # PC value for menu X| Word at 510: # CS value for menu X| X| This version of the boot block must be assembled without separate I & D X| space. X X LOADSEG = 0x0060 | here the boot block will start loading X BIOSSEG = 0x07C0 | here the boot block itself is loaded X BOOTSEG = 0x3FA0 | here it will copy itself (256K-1.5K) X DSKBASE = 120 | 120 = 4 * 0x1E = ptr to disk parameters X Xfinal = 504 Xmenu_ds = 506 Xmenu_pc = 508 Xmenu_cs = 510 X X X.globl begtext, begdata, begbss, endtext, enddata, endbss | asld needs these X.text Xbegtext: X.data Xbegdata: X.bss Xbegbss: X.text X X| copy bootblock to bootseg X mov ax,#BIOSSEG X mov ds,ax X xor si,si | ds:si - original block X mov ax,#BOOTSEG X mov es,ax X xor di,di | es:di - new block X mov cx,#256 | # words to move X rep X movw | copy loop X X X| start boot procedure X jmpi start, BOOTSEG | set cs to BOOTSEG X Xstart: X mov dx,cs X mov ds,dx | set ds to cs X xor ax,ax X mov es,ax | set es to 0 X mov ss,dx | set ss to cs i.e., stack in high core X mov sp,#1536 | initialize sp to high core X X| print greeting X mov ax,#2 | reset video X int 0x10 X X mov ax,#0x0200 | BIOS call in put cursor in ul corner X xor bx,bx X xor dx,dx X int 0x10 X mov bx,#greet X call print X X| Set up for 1.2M disk. X X xor ax,ax X mov es,ax X mov dx,ds X mov ax,#atpar X seg es X mov DSKBASE,ax X seg es X mov DSKBASE+2,dx X X xor ax,ax | reset drive X int 0x13 X X| Load the operating system from diskette. Xload: X call setreg | set up ah, cx, dx X mov bx,disksec | bx = number of next sector to read X add bx,#2 | diskette sector 1 goes at 1536 ("sector" 3) X shl bx,#1 | multiply sector number by 32 X shl bx,#1 | ditto X shl bx,#1 | ditto X shl bx,#1 | ditto X shl bx,#1 | ditto X mov es,bx | core address is es:bx (with bx = 0) X xor bx,bx | see above X add disksec,ax | ax tells how many sectors to read X movb ah,#2 | opcode for read X int 0x13 | call the BIOS for a read X jb error | jump on diskette error X mov ax,disksec | see if we are done loading X cmp ax,final | ditto X jb load | jump if there is more to load X X| Loading done. Finish up. X mov dx,#0x03F2 | kill the motor X mov ax,#0x000C X out X cli X mov bx,tracksiz | menu expects # sectors/track in bx X mov ax,menu_ds | set segment registers X mov ds,ax | when sep I&D DS != CS X mov es,ax | otherwise they are the same. X mov ss,ax | words 504 - 510 are patched by build X X seg cs X jmpi @menu_pc | jmp to menu X X| Given the number of the next disk block to read, disksec, compute the X| cylinder, sector, head, and number of sectors to read as follows: X| ah = # sectors to read; cl = sector #; ch = cyl; dh = head; dl = 0 Xsetreg: X mov si,tracksiz | 9 (PC) or 15 (AT) sectors per track X mov ax,disksec | ax = next sector to read X xor dx,dx | dx:ax = 32-bit dividend X div si | divide sector # by track size X mov cx,ax | cx = track #; dx = sector (0-origin) X mov bx,dx | bx = sector number (0-origin) X mov ax,disksec | ax = next sector to read X add ax,si | ax = last sector to read + 1 X dec ax | ax = last sector to read X xor dx,dx | dx:ax = 32-bit dividend X div tracksiz | divide last sector by track size X cmpb al,cl | is starting track = ending track X je set1 | jump if whole read on 1 cylinder X sub si,dx | compute lower sector count X dec si | si = # sectors to read X X| Check to see if this read crosses a 64K boundary (128 sectors). X| Such calls must be avoided. The BIOS gets them wrong. Xset1: mov ax,disksec | ax = next sector to read X add ax,#2 | disk sector 1 goes in core sector 3 X mov dx,ax | dx = next sector to read X add dx,si | dx = one sector beyond end of read X dec dx | dx = last sector to read X shl ax,#1 | ah = which 64K bank does read start at X shl dx,#1 | dh = which 64K bank foes read end in X cmpb ah,dh | ah != dh means read crosses 64K boundary X je set2 | jump if no boundary crossed X shrb dl,#1 | dl = excess beyond 64K boundary X xorb dh,dh | dx = excess beyond 64K boundary X sub si,dx | adjust si X dec si | si = number of sectors to read X Xset2: mov ax,si | ax = number of sectors to read X xor dx,dx | dh = head, dl = drive X movb dh,cl | dh = track X andb dh,#0x01 | dh = head X movb ch,cl | ch = track to read X shrb ch,#1 | ch = cylinder X movb cl,bl | cl = sector number (0-origin) X incb cl | cl = sector number (1-origin) X xorb dl,dl | dl = drive number (0) X ret | return values in ax, cx, dx X X X|-------------------------------+ X| error & print routines | X|-------------------------------+ X Xerror: X push ax X mov bx,#fderr X call print | print msg X xor cx,cx Xerr1: mul 0 | delay X loop err1 X int 0x19 X X Xprint: | print string (bx) X movb al,(bx) | al contains char to be printed X testb al,al | null char? X jne prt1 | no X ret | else return Xprt1: movb ah,#14 | 14 = print char X inc bx | increment string pointer X push bx | save bx X movb bl,#1 | foreground color X xorb bh,bh | page 0 X int 0x10 | call BIOS VIDEO_IO X pop bx | restore bx X jmp print | next character X X Xdisksec:.word 1 Xpcpar: .byte 0xDF, 0x02, 25, 2, 9, 0x2A, 0xFF, 0x50, 0xF6, 1, 3 | for pc Xatpar: .byte 0xDF, 0x02, 25, 2,15, 0x1B, 0xFF, 0x54, 0xF6, 1, 8 | for at X Xfderr: .asciz "Read error. Automatic reboot.\r\n" Xgreet: .asciz "\rBooting MINIX 1.5. Copyright 1991 Prentice-Hall, Inc.\r\n" Xtracksiz:.word 15 | changed to 9 for ps and pc X X| Don't forget that words 504 - 510 are filled in by build. The regular X| code had better not get that far. X.text Xendtext: X.data Xenddata: X.bss Xendbss: / echo x - /usr/src/local/tools/bootblok360.s sed '/^X/s///' > /usr/src/local/tools/bootblok360.s << '/' X| When the PC is powered on, it reads the first block from the floppy X| disk into address 0x7C00 and jumps to it. This boot block must contain X| the boot program in this file. The boot program first copies itself to X| address 256K - 1536 (to get itself out of the way). Then it loads the X| operating system from the boot diskette into memory, and then jumps to menu. X| Loading is not trivial because the PC is unable to read a track into X| memory across a 64K boundary, so the positioning of everything is critical. X| The number of sectors to load is contained at address 504 of this block. X| The value is put there by the build program after it has discovered how X| big the operating system is. When the bootblok program is finished loading, X| it jumps indirectly to the program (menu) which address is given by the X| last two words in the boot block. X| X| Summary of the words patched into the boot block by build: X| Word at 504: # sectors to load X| Word at 506: # DS value for menu X| Word at 508: # PC value for menu X| Word at 510: # CS value for menu X| X| This version of the boot block must be assembled without separate I & D X| space. X X LOADSEG = 0x0060 | here the boot block will start loading X BIOSSEG = 0x07C0 | here the boot block itself is loaded X BOOTSEG = 0x3FA0 | here it will copy itself (256K-1.5K) X DSKBASE = 120 | 120 = 4 * 0x1E = ptr to disk parameters X Xfinal = 504 Xmenu_ds = 506 Xmenu_pc = 508 Xmenu_cs = 510 X X X.globl begtext, begdata, begbss, endtext, enddata, endbss | asld needs these X.text Xbegtext: X.data Xbegdata: X.bss Xbegbss: X.text X X| copy bootblock to bootseg X mov ax,#BIOSSEG X mov ds,ax X xor si,si | ds:si - original block X mov ax,#BOOTSEG X mov es,ax X xor di,di | es:di - new block X mov cx,#256 | # words to move X rep X movw | copy loop X X X| start boot procedure X jmpi start, BOOTSEG | set cs to BOOTSEG X Xstart: X mov dx,cs X mov ds,dx | set ds to cs X xor ax,ax X mov es,ax | set es to 0 X mov ss,dx | set ss to cs i.e., stack in high core X mov sp,#1536 | initialize sp to high core X X| print greeting X mov ax,#2 | reset video X int 0x10 X X mov ax,#0x0200 | BIOS call in put cursor in ul corner X xor bx,bx X xor dx,dx X int 0x10 X mov bx,#greet X call print X X| Set up for 360K disk. X X mov tracksiz,#9 X xor ax,ax X mov es,ax X mov dx,ds X mov ax,#pcpar X seg es X mov DSKBASE,ax X seg es X mov DSKBASE+2,dx X xor ax,ax | diskette reset X int 0x13 X X| Load the operating system from diskette. Xload: X call setreg | set up ah, cx, dx X mov bx,disksec | bx = number of next sector to read X add bx,#2 | diskette sector 1 goes at 1536 ("sector" 3) X shl bx,#1 | multiply sector number by 32 X shl bx,#1 | ditto X shl bx,#1 | ditto X shl bx,#1 | ditto X shl bx,#1 | ditto X mov es,bx | core address is es:bx (with bx = 0) X xor bx,bx | see above X add disksec,ax | ax tells how many sectors to read X movb ah,#2 | opcode for read X int 0x13 | call the BIOS for a read X jb error | jump on diskette error X mov ax,disksec | see if we are done loading X cmp ax,final | ditto X jb load | jump if there is more to load X X| Loading done. Finish up. X mov dx,#0x03F2 | kill the motor X mov ax,#0x000C X out X cli X mov bx,tracksiz | menu expects # sectors/track in bx X mov ax,menu_ds | set segment registers X mov ds,ax | when sep I&D DS != CS X mov es,ax | otherwise they are the same. X mov ss,ax | words 504 - 510 are patched by build X X seg cs X jmpi @menu_pc | jmp to menu X X| Given the number of the next disk block to read, disksec, compute the X| cylinder, sector, head, and number of sectors to read as follows: X| ah = # sectors to read; cl = sector #; ch = cyl; dh = head; dl = 0 Xsetreg: X mov si,tracksiz | 9 (PC) or 15 (AT) sectors per track X mov ax,disksec | ax = next sector to read X xor dx,dx | dx:ax = 32-bit dividend X div si | divide sector # by track size X mov cx,ax | cx = track #; dx = sector (0-origin) X mov bx,dx | bx = sector number (0-origin) X mov ax,disksec | ax = next sector to read X add ax,si | ax = last sector to read + 1 X dec ax | ax = last sector to read X xor dx,dx | dx:ax = 32-bit dividend X div tracksiz | divide last sector by track size X cmpb al,cl | is starting track = ending track X je set1 | jump if whole read on 1 cylinder X sub si,dx | compute lower sector count X dec si | si = # sectors to read X X| Check to see if this read crosses a 64K boundary (128 sectors). X| Such calls must be avoided. The BIOS gets them wrong. Xset1: mov ax,disksec | ax = next sector to read X add ax,#2 | disk sector 1 goes in core sector 3 X mov dx,ax | dx = next sector to read X add dx,si | dx = one sector beyond end of read X dec dx | dx = last sector to read X shl ax,#1 | ah = which 64K bank does read start at X shl dx,#1 | dh = which 64K bank foes read end in X cmpb ah,dh | ah != dh means read crosses 64K boundary X je set2 | jump if no boundary crossed X shrb dl,#1 | dl = excess beyond 64K boundary X xorb dh,dh | dx = excess beyond 64K boundary X sub si,dx | adjust si X dec si | si = number of sectors to read X Xset2: mov ax,si | ax = number of sectors to read X xor dx,dx | dh = head, dl = drive X movb dh,cl | dh = track X andb dh,#0x01 | dh = head X movb ch,cl | ch = track to read X shrb ch,#1 | ch = cylinder X movb cl,bl | cl = sector number (0-origin) X incb cl | cl = sector number (1-origin) X xorb dl,dl | dl = drive number (0) X ret | return values in ax, cx, dx X X X|-------------------------------+ X| error & print routines | X|-------------------------------+ X Xerror: X push ax X mov bx,#fderr X call print | print msg X xor cx,cx Xerr1: mul 0 | delay X loop err1 X int 0x19 X X Xprint: | print string (bx) X movb al,(bx) | al contains char to be printed X testb al,al | null char? X jne prt1 | no X ret | else return Xprt1: movb ah,#14 | 14 = print char X inc bx | increment string pointer X push bx | save bx X movb bl,#1 | foreground color X xorb bh,bh | page 0 X int 0x10 | call BIOS VIDEO_IO X pop bx | restore bx X jmp print | next character X X Xdisksec:.word 1 Xpcpar: .byte 0xDF, 0x02, 25, 2, 9, 0x2A, 0xFF, 0x50, 0xF6, 1, 3 | for pc Xatpar: .byte 0xDF, 0x02, 25, 2,15, 0x1B, 0xFF, 0x54, 0xF6, 1, 8 | for at X Xfderr: .asciz "Read error. Automatic reboot.\r\n" Xgreet: .asciz "\rBooting MINIX 1.5. Copyright 1991 Prentice-Hall, Inc.\r\n" Xtracksiz:.word 15 | changed to 9 for ps and pc X X| Don't forget that words 504 - 510 are filled in by build. The regular X| code had better not get that far. X.text Xendtext: X.data Xenddata: X.bss Xendbss: / echo x - /usr/src/local/tools/bootblok720.s sed '/^X/s///' > /usr/src/local/tools/bootblok720.s << '/' X| When the PC is powered on, it reads the first block from the floppy X| disk into address 0x7C00 and jumps to it. This boot block must contain X| the boot program in this file. The boot program first copies itself to X| address 256K - 1536 (to get itself out of the way). Then it loads the X| operating system from the boot diskette into memory, and then jumps to menu. X| Loading is not trivial because the PC is unable to read a track into X| memory across a 64K boundary, so the positioning of everything is critical. X| The number of sectors to load is contained at address 504 of this block. X| The value is put there by the build program after it has discovered how X| big the operating system is. When the bootblok program is finished loading, X| it jumps indirectly to the program (menu) which address is given by the X| last two words in the boot block. X| X| Summary of the words patched into the boot block by build: X| Word at 504: # sectors to load X| Word at 506: # DS value for menu X| Word at 508: # PC value for menu X| Word at 510: # CS value for menu X| X| This version of the boot block must be assembled without separate I & D X| space. X X LOADSEG = 0x0060 | here the boot block will start loading X BIOSSEG = 0x07C0 | here the boot block itself is loaded X BOOTSEG = 0x3FA0 | here it will copy itself (256K-1.5K) X DSKBASE = 120 | 120 = 4 * 0x1E = ptr to disk parameters X Xfinal = 504 Xmenu_ds = 506 Xmenu_pc = 508 Xmenu_cs = 510 X X X.globl begtext, begdata, begbss, endtext, enddata, endbss | asld needs these X.text Xbegtext: X.data Xbegdata: X.bss Xbegbss: X.text X X| copy bootblock to bootseg X mov ax,#BIOSSEG X mov ds,ax X xor si,si | ds:si - original block X mov ax,#BOOTSEG X mov es,ax X xor di,di | es:di - new block X mov cx,#256 | # words to move X rep X movw | copy loop X X X| start boot procedure X jmpi start, BOOTSEG | set cs to BOOTSEG X Xstart: X mov dx,cs X mov ds,dx | set ds to cs X xor ax,ax X mov es,ax | set es to 0 X mov ss,dx | set ss to cs i.e., stack in high core X mov sp,#1536 | initialize sp to high core X X| print greeting X mov ax,#2 | reset video X int 0x10 X X mov ax,#0x0200 | BIOS call in put cursor in ul corner X xor bx,bx X xor dx,dx X int 0x10 X mov bx,#greet X call print X X| Set up for 720K disk. X X mov tracksiz,#9 X xor ax,ax | ps disk parameters are in ROM F01520 X mov es,ax X mov ax,#0x1520 X seg es X mov DSKBASE,ax X mov ax,#0xF000 X seg es X mov DSKBASE+2,ax X X xor ax,ax | diskette reset X int 0x13 X X| Load the operating system from diskette. Xload: X call setreg | set up ah, cx, dx X mov bx,disksec | bx = number of next sector to read X add bx,#2 | diskette sector 1 goes at 1536 ("sector" 3) X shl bx,#1 | multiply sector number by 32 X shl bx,#1 | ditto X shl bx,#1 | ditto X shl bx,#1 | ditto X shl bx,#1 | ditto X mov es,bx | core address is es:bx (with bx = 0) X xor bx,bx | see above X add disksec,ax | ax tells how many sectors to read X movb ah,#2 | opcode for read X int 0x13 | call the BIOS for a read X jb error | jump on diskette error X mov ax,disksec | see if we are done loading X cmp ax,final | ditto X jb load | jump if there is more to load X X| Loading done. Finish up. X mov dx,#0x03F2 | kill the motor X mov ax,#0x000C X out X cli X mov bx,tracksiz | menu expects # sectors/track in bx X mov ax,menu_ds | set segment registers X mov ds,ax | when sep I&D DS != CS X mov es,ax | otherwise they are the same. X mov ss,ax | words 504 - 510 are patched by build X X seg cs X jmpi @menu_pc | jmp to menu X X| Given the number of the next disk block to read, disksec, compute the X| cylinder, sector, head, and number of sectors to read as follows: X| ah = # sectors to read; cl = sector #; ch = cyl; dh = head; dl = 0 Xsetreg: X mov si,tracksiz | 9 (PC) or 15 (AT) sectors per track X mov ax,disksec | ax = next sector to read X xor dx,dx | dx:ax = 32-bit dividend X div si | divide sector # by track size X mov cx,ax | cx = track #; dx = sector (0-origin) X mov bx,dx | bx = sector number (0-origin) X mov ax,disksec | ax = next sector to read X add ax,si | ax = last sector to read + 1 X dec ax | ax = last sector to read X xor dx,dx | dx:ax = 32-bit dividend X div tracksiz | divide last sector by track size X cmpb al,cl | is starting track = ending track X je set1 | jump if whole read on 1 cylinder X sub si,dx | compute lower sector count X dec si | si = # sectors to read X X| Check to see if this read crosses a 64K boundary (128 sectors). X| Such calls must be avoided. The BIOS gets them wrong. Xset1: mov ax,disksec | ax = next sector to read X add ax,#2 | disk sector 1 goes in core sector 3 X mov dx,ax | dx = next sector to read X add dx,si | dx = one sector beyond end of read X dec dx | dx = last sector to read X shl ax,#1 | ah = which 64K bank does read start at X shl dx,#1 | dh = which 64K bank foes read end in X cmpb ah,dh | ah != dh means read crosses 64K boundary X je set2 | jump if no boundary crossed X shrb dl,#1 | dl = excess beyond 64K boundary X xorb dh,dh | dx = excess beyond 64K boundary X sub si,dx | adjust si X dec si | si = number of sectors to read X Xset2: mov ax,si | ax = number of sectors to read X xor dx,dx | dh = head, dl = drive X movb dh,cl | dh = track X andb dh,#0x01 | dh = head X movb ch,cl | ch = track to read X shrb ch,#1 | ch = cylinder X movb cl,bl | cl = sector number (0-origin) X incb cl | cl = sector number (1-origin) X xorb dl,dl | dl = drive number (0) X ret | return values in ax, cx, dx X X X|-------------------------------+ X| error & print routines | X|-------------------------------+ X Xerror: X push ax X mov bx,#fderr X call print | print msg X xor cx,cx Xerr1: mul 0 | delay X loop err1 X int 0x19 X X Xprint: | print string (bx) X movb al,(bx) | al contains char to be printed X testb al,al | null char? X jne prt1 | no X ret | else return Xprt1: movb ah,#14 | 14 = print char X inc bx | increment string pointer X push bx | save bx X movb bl,#1 | foreground color X xorb bh,bh | page 0 X int 0x10 | call BIOS VIDEO_IO X pop bx | restore bx X jmp print | next character X X Xdisksec:.word 1 Xpcpar: .byte 0xDF, 0x02, 25, 2, 9, 0x2A, 0xFF, 0x50, 0xF6, 1, 3 | for pc Xatpar: .byte 0xDF, 0x02, 25, 2,15, 0x1B, 0xFF, 0x54, 0xF6, 1, 8 | for at X Xfderr: .asciz "Read error. Automatic reboot.\r\n" Xgreet: .asciz "\rBooting MINIX 1.5. Copyright 1991 Prentice-Hall, Inc.\r\n" Xtracksiz:.word 15 | changed to 9 for ps and pc X X| Don't forget that words 504 - 510 are filled in by build. The regular X| code had better not get that far. X.text Xendtext: X.data Xenddata: X.bss Xendbss: / echo x - /usr/src/local/tools/config sed '/^X/s///' > /usr/src/local/tools/config << '/' Xprog=`basename $0` X Xcase $1 in X 360) drive=360;; X X 720) drive=720;; X X 1200) drive=1200;; X X clean) echo "rm -f bootblok.s" X rm -f bootblok.s X exit 0;; X X *) X echo "$prog: usage: $prog [ 360 | 720 | 1200 ]" X exit 1;; X Xesac X Xecho "cp bootblok$drive.s bootblok.s" Xcp bootblok$drive.s bootblok.s X Xecho "Now set up to build a boot image for a" $drive "k disk." X Xexit 0 / Ken Hendrickson N8DGN/6 kjh@usc.edu ...!uunet!usc!pollux!kjh