[comp.os.minix] New Bootstrapper Update Part 1 of 2

ncoverby@ndsuvax.UUCP (Glen Overby) (06/16/89)

Since I first posted my new bootstrapper, I've added support to boot
directly off of a hard disk.  Replace the files in my origional posting
(Article-IDs: {265[789],2660}@ndsuvax.UUCP) with these and install as before.

It sure is nice to be able to boot up without touching floppies!  It's a lot
faster!

		Glen Overby	<ncoverby@plains.nodak.edu>
	uunet!ndsuvax!ncoverby (UUCP)	ncoverby@ndsuvax (Bitnet)

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	README
#	b1/bootblok.asm4
#	b1/fdboot.uu
#	b1/hdboot.uu
#	b1/mfdisk.asm
#	b2b/Makefile
#	b2b/bsu.s
#	MANIFEST
# This archive created: Thu Jun 15 22:54:32 1989
export PATH; PATH=/bin:$PATH
echo shar: extracting "'README'" '(11877 characters)'
if test -f 'README'
then
    echo shar: will not over-write existing file "'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
X                  A New Bootstrapper for Minix
X                            Version 2
X
X                           Glen Overby
X                  North Dakota State University
X                       Fargo, North Dakota
X
X
X
X                          June 15, 1989
X
X
X
XThe objective of this project is to improve the verasility of the
XMinix  boot-up  process by reading the major pieces of the system
Xfrom files on a filesystem, rather than from an image diskette.
X
XIn doing this, I have completely rewritten  the  Minix  bootstrap
Xprocess.  I now have a two-stage process to load the system and a
Xspecial hard disk loader program.
X
Xthe first stage resides in the boot block of a  Minix  filesystem
Xand  is  loaded by the PC's ROM or the hard disks's loader.  When
Xstage 1 takes over, it reads the root directory of /dev/fd0 look-
Xing for a stripped file (no "a.out" header) named "boot" to load.
XAfter control is passed to stage 2, it loads four  "a.out"  files
Xcontaining  the  Kernel,  Memory  Manager,  File System and Init,
Xbuilding a normal process stacks with process arguments for each.
X
XThe new hard disk loader, written by Motti Bazar, asks  the  user
Xwhich  partition  to  boot  from, and loads that partition's boot
Xblock to 0:7C00H.  It then executes it, passing a pointer to  the
Xboot  partition's  disk  table  entry (somewhere in the relocated
Xhard disk boot loader located at 0:600H) and the cylinder  offset
Xof  the partition.  The need for these two parameters is the only
Xreason I changed from the standard DOS  boot  block  to  Motti's.
XAfter  using itI have found it nice to be able to boot off of any
Xpartition I want.
X
XThe first stage is written entirely in assembler by an  associate
Xof  mine,  Dan  Thureen.   Dan used the MicroSoft Macro Assembler
X(version 4.0 works OK; I've  had  trouble  with  5.0  complaining
Xabout  not  having a stack segment and such).  Microsoft's assem-
Xbler was used because we did  not  know  all  of  the  syntax  of
XMinix's  asld,  and  there  were  a few required addressing modes
X(such as jump indirect) that we did not know how to code.
X
XI have heavily modified Dan's origional  loader  to  support  the
Xhard drive, and to fit better with my second stage loader.
X
XStage 2 is written primarily in C, with  some  assembler  support
Xroutines.   It  loads  "a.out"  format  files  from  Minix format
Xfilesystems on any disk or partition; it knows about  partitioned
Xhard  disks as well as floppy diskettes.  After all processes are
Xloaded, stacks are built for each of the processes.  The kernel's
Xstack  contains  "struct  proc" entries for kernel memory, MM, FS
Xand Init.  These are used by the proc table  initialization  rou-
Xtines as a replacement for the sizes[] array.
X
XFile loader.c contains the code that does all of  the  filesystem
Xreading.   Routines  with double sides are the only ones intended
Xfor use outside this module.
X
X
X                                =================
X                                ||  Open_File  ||
X                                =================
X                         _______/       |       \_______
X                        /               |               \
X                ---------------         |               --------------
X                | Follow_Path |         |               | Device_Map |
X                ---------------         |               --------------
X         _______/      /    \           |
X        /            /        \         |
X-------------      /    --------------  |
X| Next_Name |    /      | Search_Dir |  |
X-------------  /        --------------  |
X             /            /             |
X           /            /               |
X         /      ===============         |               ===============
X        |       || Read_File ||         |               || Load_File ||
X        |       ===============          \              ===============
X        |               |   \_________     \               /     |
X        |               |             |      \           /       |
X--------------  -----------------     |   ____ \  _____/    -----------------
X| Read_Inode |  | L_Load_Blocks |     |  |       \          | F_Load_Blocks |
X--------------  -----------------     |  |         \        -----------------
X        \                    \        |  |   _______ \  _________/    |
X          \                   \       |  |  |          \              |
X            \                  \      |  |  |    --------------  -------------
X              \                 \     |  |  |    | Read_Super |  | Phys_Copy |
X                \                \    |  |  |    --------------  -------------
X                  \_____________  \   |  |  |   _____/      \
X                                \  \  |  |  |  /              \
X                                 --------------         -------------
X                                 | Block_Read |         | Read_Part |
X                                 --------------         -------------
X                                        |     ________________/
X                                        |    /
X                                -----------------
X                                | LL_Block_Read |
X                                -----------------
X                                        |
X                                   ----------
X                                   | diskio |
X                                   ----------
X
X
XThe filenames used by the loader  have  been  extended  to  allow
Xspecification  of  what device to load the file from, in the for-
Xmat:
X                  device[.partition]:path
X
XThe devices that loader knows about are:
X     fd0, fd1, fd2, fd3          floppy diskettes
X     hd0.1, hd0.2, hd0.3, hd0.4  hard disk 0 parititons 1-4
X     hd1.1, hd1.2, hd1.3, hd1.4  hard disk 1 parititons 1-4
X
X
XCHANGES TO  MINIX
X
XI attempted to keep the number of changes to the Minix  internals
Xto a minimum.  I think I have succeeded fairly well with this.
X
XThe Kernel start-up in mpx88 was changed to expect  arguments  on
Xthe  stack  for main.  This is passed along in the same manner as
Xfor a normal process.  The kernel's "proc"  table  initialization
Xsection copies from the arguments rather than calculating it from
Xthe "sizes" array, which no longer  exists.   The  first  element
X(argv[0])  contains  information about the kernel; the next three
Xelements (argv[1,2,3]) are for MM,  FS  and  Init,  respectively.
XWith  the  removal  of  the sizes array, changes to the interrupt
Xvector  initialization  and  memory  driver  initialization  (for
X/dev/kmem) were requred.  Set_Vec was changed to use the physical
Xdata segment of the "Hardware" process rather than calculating it
Xfrom  "base_click+sizes[0]".   The  memory  driver was similarily
Xmodified, but using the virtual address of the stack segment  for
Xthe size of the kmem driver.
X
XThe Memory Manager no longer waits for the file system to tell it
Xthe  top  of  the  ram disk; instead, it uses a call added to the
XSYSTEM process, GET_MAP, to get a  process'  segment  maps.   The
X"BRK2"  call has now been changed to allocate any size out of the
Xglobal memory pool, rather than within a process' 64K  data  seg-
Xment.   This  call is used by the file system to allocate the ram
Xdisk's memory.
X
XThe File System uses it's parameters to determine which device to
Xmount  as the root filesystem, and if it is necessary to pre-load
Xthat device from another device (i.e. if it's a ram disk).   This
Xchange  wasn't  necessary to to the bootstrap process, but it was
Xat the top of my list of change I wanted to make  and  I  did  it
Xwhile giving the bootstrapper some time to "break in".
X
XCHANGES IN THE SECOND VERSION
X
XMy first version would not load from the hard drive; this  second
Xversion has changed that.
X
XThe loader now offsets all requests with  the  cylinder  starting
Xsector  (passed  from  Motti's  hard  disk loader), and the drive
Xparameters for are configured from BIOS call 13h.  There  is  one
X"hack"  to  calculate  the  drive number when using a partitioned
Xhard drive; the partition is calculated by subtracting  an  abso-
Xlute  address from the partition table entry passed from the main
Xhard disk loader.  There is now a define to determine which  type
Xof device (floppy or hard disk) is being booted from.
X
XThe second stage program now saves the default boot device passed
Xfrom  the bootblock.  I also fixed a bug in the hard disk parame-
Xter settings; I had hard-coded the number of heads on  my  drive.
XThat is now obtained from the BIOS.
X
XFUTURE ENHACNEMENTS
X
XThe block-read makes two ROM calls to read  each  sector  of  the
Xblock.   This  should  be changed to one call, with logic for the
Xerrors returned when a track or cylinder is crossed.
X
XMemory size should be acquired from the ROM  and  passed  on  the
XMemory  Manager's stack rather than using the current memory size
Xcalculation which twiddles with the segment registers  and  pokes
Xthru all existing memory to find out how much there is there.
X
XAll RAM disk types should be separate minor devices in the Memory
Xdriver.   This  would  theoretically  allow  three  RAM disks: PC
X(under 640K), AT (Extended memory) and EMS.  Currently, it is ei-
Xther  PC  or  AT type RAM disk, determined by the size of the RAM
Xdisk.
X
XConfiguration of some device driver parameters (such as  keyboard
Xtype,  primary  printer  port,  video adapter type, and CPU type)
Xcould be done in the second stage and passed in on  the  Kernel's
Xstack.
X
XMore server processes could be configured into the system.   This
Xwould require the constant "LOW_USER" to become a variable passed
Xto the kernel.
X
XA Hard-Disk stage 1 bootstrapper needs to be written so Minix can
Xboot  fully  off  the  hard  drive.   One that might work, called
X"BOOTCODE.ASM" by W.D. Caglewas posted in Oct. 87.
X
XINSTALLING THE CHANGES
X
XMy changes add two directories to the Minix hierarchy,  "b1"  and
X"b2b".   The directory "b2b" was origionally named "b2", but what
XI'm sending out is the third major revision and  I  put  each  in
Xseparate directories.  Directory "b1" contains the first stage of
Xthe bootsrapper in source and binary.  If you wish to  reassemble
Xthe  sources,  write bootblok.asm to a dos disk and reassemble it
Xfrom dos.  Follow the instructions at the beginning of  the  code
Xfor  writing it directly to a Minix filesystem disk's boot block;
Xotherwise, run uudecode on the ".uu" file in the "b1"  directory,
Xand use
X        dd if=bootblok of=/dev/fd0
Xto write it to the boot block of a Minix filesystem.
X
XCompiling the second stage, in "b2b" simply requires a "make"  in
Xthat directory.  Before compiling you may want to change the dev-
Xice and file names of the system files in main.c.  It would real-
Xly  be  nice  to  have a configuration file to tell what files to
Xload for each piece of the system, but  I  haven't  written  that
Xyet.
X
XNext, patch all the diffs into your Kernel, FS,  MM,  header  and
Xlibrary  files,  and copy in the new mpx88.s file.  All diffs are
Xcontext diffs and require "patch" to install them.   If  you  are
Xpatching  into  a full set of Minix sources, you will not be able
Xto use the makefiles.  The way I do most  of  my  development  is
Xwith  a  parallel  copy  of  the  sources, only copying necessary
Xfiles.  My work  source  directory  is  /usr/src/minix,  and  the
Xparallel  directory is /usr/src/minix/newboot.  If you do not use
Xthe makefiles, you will need to merge some changes I have made to
Xthem  into  the generic Minix ones; first, I use "crtso.s" rather
Xthan "head.s" for FS, MM and Init.  This allows me to  link  with
X"cc"  rather  than "asld".  I have added the changed library file
X"syslib.s" to the end of my link commands so that I don't have to
Xrebuild my entire library with the changed file.  This was simply
Xeasier for testing.  Lastly, I "chmem" all  executables  down  to
X2000 bytes of stack space.
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
SHAR_EOF
if test 11877 -ne "`wc -c < 'README'`"
then
    echo shar: error transmitting "'README'" '(should have been 11877 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'b1/bootblok.asm4'" '(17454 characters)'
if test -f 'b1/bootblok.asm4'
then
    echo shar: will not over-write existing file "'b1/bootblok.asm4'"
else
sed 's/^X//' << \SHAR_EOF > 'b1/bootblok.asm4'
X	page	,132
X;-----------------------------------------------------------------------------
X;
X;			MINIX primary bootstrap loader
X;
X;	Dan Thureen
X;	Glen Overby
X;		North Dakota State University
X;		<ncoverby@plains.nodak.edu>
X;		{uunet,umn-cs}!ndsuvax!ncoverby, 
X;		ncoverby@ndsuvax (bitnet)
X;									
X;	1) ROM monitor loads bootstrap sector from floppy (512 bytes)
X;	   to address 0000:7C00 and executes starting at 7C00.
X;
X;	2) Bootstrap program loads second sector of boot block right
X;	   after the already-loaded first sector, completing the program
X;	   binary.
X;
X;	3) Loader reads superblock,  loads root directory (inode #1)
X;	   into memory and searches for file named "boot".
X;
X;	4) The file "boot" is loaded into memory at address 3200:0000
X;	   and executed.
X;
X;
X;	   The file boot is an executable image, WITHOUT an a.out header.
X;
X;	   A small library of character and string I/O routines is provided
X;	   for future expansion. Also some small debugging routines for
X;	   doing memory dumps, etc.
X;
X;	   Note: All of the code below will not fit into the 1K block
X;	   allocated by the MINIX file system for the boot block.  The
X;	   optional sections are placed at the very end and the executable
X;	   image truncated to the 1K size limit.  An expanded ( 1K+ )
X;	   version can be run on a ZENITH clone by the following steps:
X;
X;		Load it into memory with the DOS DEBUG program
X;		Move it to 3000:7C00
X;		Trap to the ROM monitor <ctrl><alt><return>
X;		Use the monitor routines to execute, single-step, etc.
X;
X;	Because the .EXE file starting address is not CS:0100 the EXE2BIN
X;	utility cannot be used to convert to a straight binary image. This
X;	can, however, be done with DEBUG.
X;
X;		DEBUG BOOTBLOK.EXE  - loads at CS:7C00
X;		-WCS:7C00 0 0 2     - writes 2 sectors to block 0,1 of drive A.
X;				      MINIX file system disk must be in drive A
X;				      for this step
X;
X;	If a DOS file image is desired use DEBUG again:
X;
X;		DEBUG BOOTBLOK.EXE  - loads at CS:7C00, sets BX:CS to file size
X;		-NBOOTBLOK	    - select name for image file
X;		-RBX
X;		BX xxxx
X;		:0000		    - set image file size to 1024 bytes (400h)	
X;		-RCX
X;               CX xxxx
X;		:0400
X;		-WCS:7C00	    - write 1024 bytes to file from CS:7C00
X;
X;	This can be transferred to MINIX using dosread and patched in with dd.
X;
X; Changes:
X;
X; 01/10/88 DT	Initial Release, for NDSU CS548
X;		This release loaded a Minix image (built with "build")
X;		from the "/boot" file.
X; 03/01/88 GPO	Start adding an inteligent second stage.
X; 		Leave 1st stage at 0:7C00 and load second stage to 3200:0
X; 04/29/88 GPO	Reduce the ammount of chatter
X; 06/05/89 GPO	Support hard disk bootstrapper.
X;		Requires the multi-partition hard disk boot loader
X;		by Motti Bazar.
X;		Added the "HARD_DISK" variable.  Rerequires separate
X;		compilation for hard disk and floppy versions.
X;		Drive number is passed to stage 2 in BX
X;		if DEBUG is not defined, don't even assemble unneded code.
X;-----------------------------------------------------------------------------
X
X_text	segment	para public 'code'
X	assume	cs:_text, ds:_text	; Tiny data model with CS=DS=SS	
X
XDEBUG			EQU	0	; Set non-0 if debug code to be
X					; included
X
XHARD_DISK		EQU	01	; Set non-zero if this will be in
X					; the boot sector of a hard disk
X
XS_IMAP_BLOCKS_OFF	equ	4
XS_ZMAP_BLOCKS_OFF	equ	6
XNR_DZONE_NUM		equ	7
XI_ZONE_OFF		equ	14
XI_SIZE_OFF		equ	4
XIND_ZONE_OFF		equ	28	
XBOOT_2_SEG		equ	3200h	; Where the second stage boot program
XBOOT_2_OFF		equ	0000h	; is loaded to
XBOOT_OFF		equ	7c00h	; starting point of Boot1
X
XBOOT_2	segment at BOOT_2_SEG		; Define starting segment address
X					; for second stage boot program.
X	org	BOOT_2_OFF              ; Entry point at offset 0000.
Xstage2	label	byte
XBOOT_2	ends
X
X	org	BOOT_OFF
Xstart1:
X	mov	ax, cs			; set up segment registers
X	mov	ds, ax                  ; tiny memory model CS=DS=SS
X	mov	ss, ax
X	mov	sp, offset estack       ; CS=AX=HIGH_BOOT_SEG?
X
Xif	HARD_DISK
X	; the hard disk boot loader will pass the starting cylinder of the
X	; partition in BS, and the partition entry at (now destroyed) DS:SI.
X	mov	startcyl, bx		; save starting cylinder
X	mov	partoff, si		; save ptr to partition table
X	; Calculate tracksiz and cylsize from ROM parameters
X	mov	ah, 8			; Return current drive parameters
X	mov	dl, drive		; hard-disk
X	int	013h
X	and	cl, 03Fh		; discard cylinder number high bits
X	xor	ch, ch			; CX - Number of sectors per track
X	mov	tracksize, cx
X	mov	al, dh			; cylsize = heads * tracksize
X	inc	al
X	xor	ah, ah
X	mul	cl
X	mov	cylsize, ax
Xendif
X
X	call	reset			; reset drive
X
X	mov	lsn, 1			; read the boot block's second sector
X	mov	bx, ds			; from disk (partition) sector 1.
X	mov	es, bx			; (the ROM or Hard Disk primary boot
X	mov	bx, 7e00h		; only loads the first sector
X	call	read_sector
Xdie:	jc	die			; if there's a read error now, hang.
X					; message printing isn't loaded!
X
Xif	DEBUG
X	mov	ax, offset block_buf    ; hex dump of boot block
X	push	ax
X	call	_print_block
X	pop	ax
X        call	getchar                 ; wait for key pressed
Xendif
X
Xif	DEBUG
X	call	_newline		; print tracksize, cylsize and 
X	mov	ax, tracksize		; starting cylinder
X	call	put4x
X	mov	al, ' '
X	call	putchar
X	mov	ax, cylsize
X	call	put4x
X	mov	al, ' '
X	call	putchar
X	mov	ax, startcyl
X	call	put4x
X	call	_newline
Xendif
X
X	mov	inode_no, 1             ; load root directory (inode=1)
X	mov	fseg, ds
X	mov	foff, offset dir_buf
X	call	load_file
X
Xif	DEBUG
X	call	_newline
X	mov	ax, n_blocks		; show file size	
X	call	put4x
X	call	_newline
Xendif
X
X	mov	ax, n_blocks            ; loop to search for file "boot"
X	mov	cl, 10
X	shl	ax, cl			; ax = # of bytes in directory
X	mov	bx, 0
Xsearch_loop:
X	cmp	bx, ax                  ; bx = byte offset within directory
X	jge	no_match
X	cmp	word ptr dir_buf[bx], 0 ; ignore files with inode# 0
X	je	next_name
X	lea	si, dir_buf+2[bx]	; compare filename with boot_file_name
X	lea	di, boot_file_name
X	call	strcmp
X	je	found_file
Xnext_name:
X	add	bx, 16				; next directory entry
X	jmp	search_loop
Xno_match:
X	mov	bx, offset not_found_err	; file not found
X	jmp	terminate
Xfound_file:
X	mov	ax, word ptr dir_buf[bx]	; get inode #
X	mov	inode_no, ax
X
X	mov	fseg, BOOT_2_SEG		; load file to BOOT_2_SEG
X	mov	foff, 0
X;	mov	fseg, ds			; test load into data segment
X;	mov	foff, offset    fil_buf
X
X	call	load_file
X
Xif	DEBUG
X	mov	bx, offset file_loaded
X	call	puts
X	mov	ax, n_blocks
X	call	put4x
X	call	_newline
X	call	getchar
Xendif
X
Xget_equals:
X	mov	bx, offset ram_load
X	call	puts
Xif	DEBUG
X	call	getchar			; pause for contemplation...
X	cmp	al, '='
X	jne	get_equals
Xendif
X
Xif	HARD_DISK
X	mov	ax, partoff	; Drive = Partition + 41h
X	sub	ax, 7beh	; !!!! Warning: Loader dependent address !!!!
X	mov	cl, 16
X	div	cl
X	xor	ah, ah
X	add	ax, 41h
X	mov	dx, ax
Xelse
X	mov	dl, drive		; send drive in DX
X	xor	dh, dh
Xendif
X	jmp	far ptr stage2
X
Xreset:	xor	ah, ah
X	mov	dl, drive
X	int	13h
X	ret
X
Xread_block:				; lbn = logical block #
X					; bseg_no = segment#
X					; boff_no = offset
X	mov	ax, lbn
Xif	DEBUG
X	call	put4x
X	call	_newline
Xendif
X	mov	ax, lbn
X	add	ax, ax			; sector #  =  2 * block #	
X	mov	lsn, ax
X
X	mov	bx, ds                  ; es:bx = block load address
X	mov	es, bx                  ; use double buffering to avoid
X	mov	bx, offset block_buf	; DMA across 64K boundary problems
X
X	call	read_sector
X        jc	done_read_block		; read error
X	inc	lsn
X
X	mov	bx, offset block_buf + 512	; load 2nd sector of block
X	call	read_sector		
X	jc	done_read_block		; read error
X
Xmovit:	lea	si, block_buf           ; move block form buffer
X	mov	di, bseg_no		; to desired address (bseg_no:boff_no)
X	mov	es, di
X	mov	di, boff_no
X	mov	cx, 512
X	cld				
X	rep	movsw
X	
Xdone_read_block:
X	ret
X
Xread_sector:				; lsn = logical sector #
X					; ES = segment#
X					; BX = offset
X	mov	retry, 10
Xread_again:
X	dec	retry			; retry 9 more times on error
X	js	done_read_sector		; abort
X
X	mov	ax, lsn
X
X	xor	dx, dx			; dx:ax / cylinder size
X	div	cylsize
X	add	ax, startcyl		; add HD partition start cylinder
X	mov	cl, ah			; high bits of cl get bits 8,9 of
X	ror	cl, 1			; cylinder #
X	ror	cl, 1
X	mov	ch, al			; low byte of cylinder #
X	mov	ax, dx
X	xor	dx, dx
X	div	tracksize
X	mov	dh, al			; dh = head #
X	or	cl, dl			; or in sector # bits
X	inc	cl 			; start sector # at 1 rather than 0
X	mov	dl, drive		; drive #
X	mov	ax, 0201h		; read 1 sector
X	int	13h
X
X	jc	read_again		; try again on error
Xdone_read_sector:
X	ret
X
Xget_inode:				; input: inode_no
X					; returns pointer to corresponding
X					; inode in inode_p
X
X	mov	lbn, 1			; fetch super_block
X	mov	bseg_no, ds
X	mov	boff_no, offset super_buf
X	call	read_block
X	jnc	okay_super
Xif	DEBUG
X      	call	read_error
Xendif
X      	mov	bx, offset super_err
X      	jmp	terminate
X
Xokay_super:
X
Xif	DEBUG
X	mov	ax, offset super_buf
X	push	ax
X	call	_print_block
X	pop	ax
X        call	getchar
Xendif
X
X	mov	ax, inode_no
X	dec	ax
X	xor	dx, dx
X	div	inodes_per_block
X	mov	i_offset, dx
X	add	ax, super_buf + S_IMAP_BLOCKS_OFF
X	add	ax, super_buf + S_ZMAP_BLOCKS_OFF
X	add	ax, 2
X	mov	i_block, ax
X	mov	lbn, ax
X	mov	bseg_no, ds
X	mov	boff_no, offset inode_buf
X	call	read_block
X	jnc	okay_inode
X
Xif	DEBUG
X      	call	read_error
Xendif
X      	mov	bx, offset inode_err
X      	jmp	terminate
X
Xokay_inode:
X
Xif	DEBUG
X	mov	ax, offset inode_buf
X	push	ax
X	call	_print_block
X	pop	ax
X        call	getchar
Xendif
X
X	mov	bx, i_offset
X	mov	cx, 5
X	shl	bx, cl
X	add	bx, offset inode_buf
X	mov	inode_p, bx
X	ret
X
X; The following variables  must be located in the first 512 bytes
X; because they are used in the primary stage running at 0000:7C00 and the
X; BIOS ROM only loads 1 sector
Xcylsize		dw	12h		; defaults for 48 TPI floppy
Xtracksize	dw	09h
Xif HARD_DISK
X	drive	db	080h
Xelse
X	drive	db	0
Xendif
Xstartcyl	dw	0
Xpartoff		dw	0
Xblock_size	dw	1024
Xinodes_per_block dw	32		
X
X;-----------------------------------------------------------------------------
X;	The boot signature 
X;	identifies this partition as containing a valid boot program
X;
X;	This marks the end of the first sector of the stage 0 bootstrapper.
X;	Beware that the basic necessities of the bootstrapper must fit in
X;	the first sector!  The rest of the bootstrapper must fit in the 
X;	second sector of the boot block.
X;-----------------------------------------------------------------------------
X
X	org	07dfeh
X	dw	0AA55h
X
X;-----------------------------------------------------------------------------
X
Xload_file:			; load file at fseg:foff given inode_no
X				; returns file size in n_blocks
X	call	get_inode
X	mov	bx, inode_p
X	mov	ax, I_SIZE_OFF[bx]	
X        mov	dx, I_SIZE_OFF+2[bx]
X        div	block_size
X        mov	n_blocks, ax    ; calculate # of blocks to load
X        test	dx, dx
X        jz	no_spill
X        inc	n_blocks	; partial block
Xno_spill:
X	cmp	n_blocks, NR_DZONE_NUM	; are there indirect blocks?
X	jle	no_indirect
X	mov	ax, IND_ZONE_OFF[bx]	; if so, read indirect block first
X	mov	lbn, ax
X	mov	bseg_no, ds
X	mov	boff_no, offset ind_buf
X	call	read_block
X	jnc	no_indirect
X
Xif	DEBUG
X      	call	read_error
Xendif
X      	mov	bx, offset ind_err
X      	jmp	terminate
X
Xno_indirect:    		; set up loop to read all blocks in file
X	mov	ax, fseg
X	mov	bseg_no, ax
X	mov	ax, foff
X	mov	boff_no, ax
X	mov	load_i, 0
Xload_loop:
X	mov	bx, load_i      	; for load_i := 0 to n_blocks-1 do
X	cmp	bx, n_blocks
X	jge	done_load
X	add	bx, bx                  ; calculate block#
X	cmp	bx, NR_DZONE_NUM*2
X	jge	indirect_block
X	add	bx, inode_p
X	mov	ax, I_ZONE_OFF[bx]
X	jmp	cont_load
Xindirect_block:
X	mov	ax, ind_buf-14[bx]
Xcont_load:				; read the block
X	mov	lbn, ax
X	call	read_block
X	jnc	next_block
X
Xif	DEBUG
X      	call	read_error
Xendif
X      	mov	bx, offset file_err
X      	jmp	terminate
X
Xnext_block:
X
Xif DEBUG
X	mov	ax, bseg_no		; print segment:offset loaded to
X	call	put4x
X	mov	al, ':'
X	call	putchar
X	mov	ax, 0
X	call	put4x
X	call	_newline
Xendif
X	add	bseg_no, 40h		; increment seg for next block
X	inc	load_i
X	jmp	load_loop
Xdone_load:
X	ret
X
Xstrcmp:					; string compare
X	push	ds
X	pop	es			; addresses in SI & DI
X	cld
X	mov	cx, 0Eh
X	repe	cmpsb
X	ret				; returns with flags set based
X					; upon compare result	
X
Xram_load	db	13, 10, 'Second boot stage loaded. '
Xif	DEBUG
X		db	'Type "=" to start MINIX ->  ', 0
Xelse
X		db	'Starting ...', 13, 10, 0
Xendif
X;boot_err	db	'Error reading Boot block', 13, 10, 0
Xsuper_err	db	'Error reading Super_block', 13, 10, 0
Xinode_err	db	'Error reading Inode', 13, 10, 0
Xind_err		db	'Error reading Indirect Block', 13, 10, 0
Xfile_err	db	'Error reading file', 13, 10, 0
Xnot_found_err	db	'Boot file not found', 13, 10, 0
Xif DEBUG
Xfile_loaded	db	'File loaded - blocks = ', 0
Xendif
Xboot_file_name	db	'boot', 12 dup (0)
X
X;-----------------------------------------------------------------------------
X;	I/O Routines.  Many can be eliminated if the program grows too large
X;	to fit in 1K.
X;-----------------------------------------------------------------------------
X
Xterminate:
X	call	puts
Xexit:	jmp	exit			; hang in harmless loop on error
X	
Xputchar:				; char in AL, return code in AX
X	mov	ah, 0Eh
X	xor	bl, bl
X	int	10h
X	ret
X
Xputs: 					; print string, address in BX
X	mov	al, byte ptr [bx]
X	test	al, al
X	je	doneputs
X	push	bx
X	call	putchar
X	pop	bx
X	inc	bx
X	jmp	puts
Xdoneputs:
X	ret
X
X
X;-----------------------------------------------------------------------------
X;
X;	All routines which follow are optional, mostly character I/O
X;	procedures for debugging purposes, which can be stripped out
X;	if necessary.  Total code and initialized data must come first
X;	and must fit into 1K.
X;
X;-----------------------------------------------------------------------------
X
Xif	DEBUG
X_newline:
X	mov	al, 13
X	call	putchar
X        mov	al, 10
X        call	putchar
X        ret
X
Xgetchar:				; char returned in AL
X	xor	ah, ah
X	int	16h
X	cmp	al, 03h
X	je	exit
X	push	ax
X	push	bx
X	call	putchar
X	pop	bx
X	pop	ax
X	ret			
X
Xgets:					; read string into buffer
X	call	getchar			; address in bx
X	cmp	al, 0Dh
X	je	done_gets
X	mov	byte ptr [bx], al
X	inc	bx
X	jmp	gets
Xdone_gets:
X	mov	byte ptr [bx], 0
X	ret
Xendif	;!
Xput2x:					; print hex byte in AL
X	push 	ax
X	shr     ax, 1
X	shr     ax, 1
X	shr     ax, 1
X	shr     ax, 1
X	call	put_byte
X	pop	ax
Xput_byte:
X	and	al, 0Fh	
X	add	al, 30h
X	cmp	al, 39h
X	jle	nothex
X	add	al, 07h
Xnothex: call	putchar
X	ret
X
Xput4x:					; print hex word in AX
X	push	ax
X	xchg	al, ah
X	call	put2x
X	pop	ax
X	call	put2x
X	ret
Xif 	DEBUG	;!
Xread_error:
X	push	ax
X	push	bx
X	push	es
X	push	cx
X	push	dx
X	push	cx
X	push	dx
X	call	_newline
X
X	pop	ax		; print drive#
X	call	put2x
X	mov	al, ' '
X	call	putchar
X	
X	pop	ax		; print cylinder#
X	xchg	ah, al
X	call	put2x
X	mov	al, ' '
X	call	putchar
X
X	pop	ax		; print head#
X	xchg	ah, al
X	call	put2x
X	mov	al, ' '
X	call	putchar
X
X	pop	ax		; print sector#
X	call	put2x
X	mov	al, ' '
X	call	putchar
X
X	pop	ax		; print segment
X	call	put4x
X	mov	al, ':'
X	call	putchar
X
X	pop	ax		; print offset
X	call	put4x
X	call	_newline
X
X        pop	ax
X	mov	al, ah
X	call	put2x
X	mov	al, ' '
X	call	putchar
X	ret
X
X
X_print_block	proc	near
X	push	bp
X	mov	bp,sp
X	push	word ptr [bp+4]
X	call	near ptr _print_sector
X	pop	cx
X	mov	ax,word ptr [bp+4]
X	add	ax,512
X	push	ax
X	call	near ptr _print_sector
X	pop	cx
X@1:
X	pop	bp
X	ret	
X_print_block	endp
X
X
X_print_sector	proc	near
X	push	si
X	push	di
X	push	bp
X	mov	bp,sp
X	dec	sp
X	dec	sp
X	xor	si,si
X	call	near ptr _newline
X	xor	di,di
X	jmp	short @6
X@5:
X	mov	ax, si
X	call	put4x
X	mov	bx, offset _s@
X	mov	word ptr [bp-2],0
X	jmp	short @10
X@9:
X	mov	ax,si
X	inc	si
X	mov	bx,ax
X	add	bx,word ptr [bp+8]
X	mov	al,byte ptr [bx]
X	call	put2x
X	mov	al,' '
X	call	putchar
X@8:
X	inc	word ptr [bp-2]
X@10:
X	cmp	word ptr [bp-2],16
X	jb	@9
X@7:
X	mov	ax,16
X	push	ax
X	mov	ax,word ptr [bp+8]
X	add	ax,si
X	add	ax,-16
X	push	ax
X	call	near ptr _prints
X	pop	cx
X	pop	cx
X@4:
X	inc	di
X@6:
X	cmp	di,32
X	jb	@5
X@3:
X	call	near ptr _newline
X@2:
X	mov	sp,bp
X	pop	bp
X	pop	di
X	pop	si
X	ret	
X_print_sector	endp
X
X
X_prints	proc	near
X	push	si
X	push	di
X	push	bp
X	mov	bp,sp
X	mov	si,word ptr [bp+8]
X	mov	bx,offset _s@+3
X	call	puts
X	xor	di,di
X	jmp	short @15
X@14:
X	cmp	byte ptr [si],32
X	jl	@16
X	cmp	byte ptr [si],126
X	jg	@16
X	mov	al,byte ptr [si]
X	call 	putchar
X	jmp	short @17
X@16:
X	mov	al, '.'
X	call	putchar
X@17:
X@13:
X	inc	di
X	inc	si
X@15:
X	cmp	di,word ptr [bp+10]
X	jl	@14
X@12:
X	call	near ptr _newline
X@11:
X	pop	bp
X	pop	di
X	pop	si
X	ret	
X_prints	endp
X
X_s@	label	byte
X	db	32
X	db	32
X	db	0
X	db	32
X	db	32
X	db	32
X	db	32
X	db	0
X
Xendif
X
X;-----------------------------------------------------------------------------
X;
X;	Most of the following declarations are necessary but are all
X;	uninitialized data areas so they can go anywhere after the
X;	necessary code. Declarations which are followed by * are for
X;	debug purposes only.
X;
X;-----------------------------------------------------------------------------
X
X
Xretry		db	?	; dist read retry counter
Xlbn		dw	?	; logical block #
Xbseg_no		dw	?	; block load segment #
Xboff_no		dw	?	; block load offset  #
Xlsn		dw	?	; logical sector #
X
Xi_block		dw	?	; inode block #
Xi_offset	dw	?	; inode block offset
Xinode_no	dw	?	; inode number
Xinode_p		dw	?	; pointer to inode structure
X
Xload_i		dw	?	; loop counter for file load
Xfseg		dw	?       ; segment for file load
Xfoff		dw	?	; offset for file load
Xn_blocks	dw	?       ; file size in blocks
X
Xblock_buf	db	1024 dup (?)	; I/O buffer for all disk reads
X;boot_buf	db	1024 dup (?)    ; Boot block copied here
Xsuper_buf	dw	512  dup (?)    ; Super block loaded here
Xinode_buf	dw	512  dup (?)    ; Inode block loaded here
Xind_buf		dw	512  dup (?)    ; Indirect block loaded here (sometimes)
Xdir_buf		dw	512  dup (?)	; root file directory loaded here
X;fil_buf		db	20 dup (1024 dup (?))	; temporary file load area
X
Xstack		dw	100 dup (?)     ; small stack area for boot only
Xestack 		label	word            ; init SP here
X
X_text	ends
X
X	end start1
SHAR_EOF
if test 17454 -ne "`wc -c < 'b1/bootblok.asm4'`"
then
    echo shar: error transmitting "'b1/bootblok.asm4'" '(should have been 17454 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'b1/fdboot.uu'" '(1437 characters)'
if test -f 'b1/fdboot.uu'
then
    echo shar: will not over-write existing file "'b1/fdboot.uu'"
else
sed 's/^X//' << \SHAR_EOF > 'b1/fdboot.uu'
Xbegin 644 fdboot
XMC,B.V([0O&N4Z'D QP:1?P$ C-N.P[L ?NBJ '+^QP:7?P$ C!Z=?\<&GW^C
XMC^C/ :&A?[$*T^"[   [V'T9@[^CCP!T#8VWI8^-/CE_Z#@"= N#PQ#KX[LC
XM?^GK HN'HX^CEW_'!IU_ #+'!I]_  #HC &[DG[HVP**%F9],O;J    ,C+D
XMBA9F?<T3PZ&+?Z&+?P/ HY%_C-N.P[NC?^@C '(@_P:1?[NC@>@7 '(4C3:C
XM?XL^C7^.QXL^CW^Y  +\\Z7#Q@:*?PJ0_@Z*?W@NH9%_,]+W-F)] P9G?8K,
XMT,G0R8KHB\(STO<V9'V*\ K*_L&*%F9]N $"S1-RS,/'!HM_ 0",'HU_QP:/
XM?Z.#Z'K_<P:[O7[I+0*AEW](,]+W-FU]B1:5?P,&IX,#!JF#!0( HY-_HXM_
XMC!Z-?\<&CW^CA^A&_W,&N]E^Z?D!BQZ5?[D% -/C@<.CAXD>F7_#$@ )    
XM      0@                                                    
XM                                                            
XM                                                            
XM                    5:KH_OZ+'IE_BT<$BU<&]S9K?:.A?X72= 3_!J%_
XM@SZA?P=^&XM''*.+?XP>C7_'!H]_HXOH6/YS!KOO?ND+ :&=?Z.-?Z&??Z./
XM?\<&FW\  (L>FW\['J%_?2X#VX/[#GT* QZ9?XM'#NL%D(N'E8NCBW_H&?YS
XM!KL.?^G, (,&C7] _P:;?^O(PQX'_+D. /.FPPT*4V5C;VYD(&)O;W0@<W1A
XM9V4@;&]A9&5D+B!3=&%R=&EN9R N+BX-"@!%<G)O<B!R96%D:6YG(%-U<&5R
XM7V)L;V-K#0H 17)R;W(@<F5A9&EN9R!);F]D90T* $5R<F]R(')E861I;F<@
XM26YD:7)E8W0@0FQO8VL-"@!%<G)O<B!R96%D:6YG(&9I;&4-"@!";V]T(&9I
XM;&4@;F]T(&9O=6YD#0H 8F]O=                .@) .O^M XRV\T0PXH'
XMA,!T"%/H[_];0^ORPU#1Z-'HT>C1Z.@! %@D#P0P/#E^ @0'Z-#_PU"&Q.C?
XM_UCHV__#                                                    
XM                                                            
XB                                                
X 
Xend
SHAR_EOF
if test 1437 -ne "`wc -c < 'b1/fdboot.uu'`"
then
    echo shar: error transmitting "'b1/fdboot.uu'" '(should have been 1437 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'b1/hdboot.uu'" '(1437 characters)'
if test -f 'b1/hdboot.uu'
then
    echo shar: will not over-write existing file "'b1/hdboot.uu'"
else
sed 's/^X//' << \SHAR_EOF > 'b1/hdboot.uu'
Xbegin 644 hdboot
XMC,B.V([0O&N4B1Z6?8DVF'VT"(H6E7W-$X#A/S+MB0Z3?8K&_L RY/;AHY%]
XMZ(0 QP:1?P$ C-N.P[L ?NBU '+^QP:7?P$ C!Z=?\<&GW^CC^BK :&A?[$*
XMT^"[   [V'T9@[^CCP!T#8VWI8^-/CE_Z!0"= N#PQ#KX[LC?^G' HN'HX^C
XMEW_'!IU_ #+'!I]_  #H: &[DG[HMP*AF'TMO@>Q$/;Q,N0%00"+T.H    R
XM,N2*%I5]S1/#H8M_H8M_ \"CD7^,VX[#NZ-_Z", <B#_!I%_NZ.!Z!< <A2-
XM-J-_BSZ-?X['BSZ/?[D  OSSI</&!HI_"I#^#HI_>"ZAD7\STO<VD7T#!I9]
XMBLS0R=#)BNB+PC/2]S:3?8KP"LK^P8H6E7VX 0+-$W+,P\<&BW\! (P>C7_'
XM!H]_HX/H>O]S!KN]?NG^ :&7?T@STO<VG'V)%I5_ P:G@P,&J8,% @"CDW^C
XMBW^,'HU_QP:/?Z.'Z$;_<P:[V7[IR@&+'I5_N04 T^.!PZ.'B1Z9?\,2  D 
XM@       !"                                                  
XM                                                            
XM                    5:KH+?^+'IE_BT<$BU<&]S::?:.A?X72= 3_!J%_
XM@SZA?P=^&XM''*.+?XP>C7_'!H]_HXOHA_YS!KOO?ND+ :&=?Z.-?Z&??Z./
XM?\<&FW\  (L>FW\['J%_?2X#VX/[#GT* QZ9?XM'#NL%D(N'E8NCBW_H2/YS
XM!KL.?^G, (,&C7] _P:;?^O(PQX'_+D. /.FPPT*4V5C;VYD(&)O;W0@<W1A
XM9V4@;&]A9&5D+B!3=&%R=&EN9R N+BX-"@!%<G)O<B!R96%D:6YG(%-U<&5R
XM7V)L;V-K#0H 17)R;W(@<F5A9&EN9R!);F]D90T* $5R<F]R(')E861I;F<@
XM26YD:7)E8W0@0FQO8VL-"@!%<G)O<B!R96%D:6YG(&9I;&4-"@!";V]T(&9I
XM;&4@;F]T(&9O=6YD#0H 8F]O=                .@) .O^M XRV\T0PXH'
XMA,!T"%/H[_];0^ORPU#1Z-'HT>C1Z.@! %@D#P0P/#E^ @0'Z-#_PU"&Q.C?
XM_UCHV__#                                                    
XM                                                            
XB                                                
X 
Xend
SHAR_EOF
if test 1437 -ne "`wc -c < 'b1/hdboot.uu'`"
then
    echo shar: error transmitting "'b1/hdboot.uu'" '(should have been 1437 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'b1/mfdisk.asm'" '(17596 characters)'
if test -f 'b1/mfdisk.asm'
then
    echo shar: will not over-write existing file "'b1/mfdisk.asm'"
else
sed 's/^X//' << \SHAR_EOF > 'b1/mfdisk.asm'
X        page    ,132
X        title   MFDISK - FDISK clone & multiple boot-record modifier
X  
X;------------------------------------------------------------------------------
X;       This program will write a new boot sector to the first HD drive
X;       that prompts for the partition you want to boot from (1-4).
X;       To the question 'Boot partition (1-4):' you have to answer with
X;       the number of the partition you want to boot from (1-4).
X;
X;       The program must be compiled as a .COM file (remember exe2bin)
X;       and run under MesSDOS.
X;
X;       The makefile for compiling under MesSDOS should look like:
X;
X;           mfdisk.obj:  mfdisk.asm
X;                        masm mfdisk;
X;
X;           mfdisk.com:  mfdisk.obj
X;                        link mfdisk;
X;                        exe2bin mfdisk.exe mfdisk.com
X;                        del mfdisk.exe
X;
X;       When the program is run, it produces a message telling you what
X;       it is going to do. At this time you can abort it by typing
X;       <CTRL-C> or type <CR> to allow it to modify the hard-disk.
X;
X;       Now you can boot multiple operating systems (MesSDOS, OS/2,
X;       SCO Xenix and Minix) from the same hard-disk). To do so you
X;       had to partition your hard-disk to separate partitions, each
X;       with another operating-system boot.
X;
X;           Motti (Mordehai) Bazar
X;
X;           uucp    : ..uunet!ocsmd!motti
X;           bitnet  : motti%ocsmd@uunet.uu.net
X;           internet: motti@ocsmd.uu.net  OR
X;                     resrote@gwusun.gwu.edu (put my name on subject line)
X;
X;           snail:    Online Computer Systems, Inc.
X;                     20251 Century Blvd.
X;                     Germantown, MD 20874
X;
X;           vox:      (301) 428-3700
X;
X;
X;       This utility is distributed for personal use only. Use it, modify it
X;       or do anything you like, just live this comment and let me know of
X;       any bugs or enhancements you made to it, thanks.
X;
X;------------------------------------------------------------------------------
X  
X  
X;-------------------------
X; First, some definitions
X;-------------------------
X  
XVIDEO   equ     10h
XKBD     equ     16h
XDISKIO  equ     13h
XDOS     equ     21h
X  
XCR      equ     0Dh
XLF      equ     0Ah
X  
X  
X;---------------------------
X; Here comes the real thing
X;---------------------------
X  
XCODE    segment byte public 'CODE'
X        assume  cs:CODE, ds:CODE
X  
X        org     100h
X  
XWRITBOOT:
X        jmp     START                           ; jump around
X  
XDISKBUF db      512 dup(?)
X  
XHELLOMS db      CR, LF
X        db      'MFDISK - Multiple boot FDISK clone', CR, LF
X        db      CR, LF
X        db      'This program will read the boot sector from the first disk', CR, LF
X        db      'and merge the partition table from it with the boot program', CR, LF
X        db      'supplied and write it all back to the disk overlaying what', CR, LF
X        db      'was there. The resultant boot program will prompt for the', CR, LF
X        db      'desired partition for booting (1-4).', CR, LF
X        db      CR, LF
X        db      'The original boot program will be saved in a file named', CR, LF
X        db      'IBMBOOT.SVE in the default directory.', CR, LF
X        db      CR, LF
X        db      '<CR> = continue, CONTROL-C = abort ... $'
X  
XCRLF    db      CR, LF, '$'
X  
XIBMBOOT db      'IBMBOOT.SVE',0
X  
XOKMSG   db      CR, LF, 'Boot sector updated', CR, LF, '$'
XERMSG1  db      CR, LF, 'Error reading boot sector', CR, LF, '$'
XERMSG2  db      CR, LF, 'Cannot open save file', CR, LF, '$'
XERMSG3  db      CR, LF, 'Cannot write save file', CR, LF, '$'
XERMSG4  db      CR, LF, 'Cannot close save file', CR, LF, '$'
XERMSG5  db      CR, LF, 'Cannot write boot sector', CR, LF, '$'
X  
XBOOTHDL dw      0                               ; Boot backup file handle
X  
X  
XSTART:
X        ;----------------------
X        ; Show opening message
X        ;----------------------
X        mov     dx, offset HELLOMS
X        mov     ah, 9
X        int     DOS
X  
XRDCNS:
X        ;---------------------------------------------------------
X        ; Get user's response: <CR> or CONTROL-C (aborted by DOS)
X        ;---------------------------------------------------------
X        mov     ah, 0Ch
X        mov     al, 1
X        int     DOS
X        cmp     al, CR                          ; <CR> key ?
X        jne     RDCNS                           ;  No, retry
X  
X        ;-----------------------------------------
X        ; <CR> typed, go and modify the hard-disk
X        ;-----------------------------------------
X        mov     dx, offset CRLF                 ; Echo <CR><LF>
X        mov     ah, 9
X        int     DOS
X  
X        ;------------------------------------
X        ; Read the sector from the hard-disk
X        ;------------------------------------
X        mov     si, 5                           ; Retry for 5 times
XRDDSK:
X        push    si                              ; Save retry counter
X        mov     ah, 2                           ; Read disk
X        mov     al, 1                           ; 1 sector
X        mov     bx, offset DISKBUF              ; Point to buffer
X        mov     ch, 0                           ; Cylinder 0
X        mov     cl, 1                           ; Sector 1
X        mov     dh, 0                           ; Track 0
X        mov     dl, 80h                         ; Harddisk 0
X        int     DISKIO
X        pop     si
X        jnc     RDOK                            ; Good read
X        dec     si                              ; More tries?
X        jnz     RDDSK                           ;  Yes, try again
X        mov     dx, offset ERMSG1               ;  No, point to trouble message
X        mov     ah, 9                           ; say console write
X        int     DOS                             ; can't read boot sector
X        mov     ah, 4Ch                         ; say terminate
X        mov     al, 1                           ; error return code
X        int     DOS
X  
X        ;---------------------------------
X        ; Create the file to save it into
X        ;---------------------------------
XRDOK:
X        mov     dx, offset IBMBOOT              ; get file name
X        mov     ah, 3Ch                         ; say create it
X        sub     cx, cx                          ; zero attribute
X        int     DOS
X        jnc     OPENOK                          ; file opened
X        mov     dx, offset ERMSG2               ; can't open save file
X        mov     ah, 9
X        int     DOS                             ; tell 'em
X        mov     ah, 4Ch                         ; say terminate
X        mov     al, 2                           ; reason
X        int     DOS
X  
X        ;---------------------------------
X        ; Write sector to the backup file
X        ;---------------------------------
XOPENOK:
X        mov     BOOTHDL, ax                     ; save handle
X        mov     bx, ax                          ; and put in bx
X        mov     ah, 40h                         ; say write to file
X        mov     dx, offset DISKBUF              ; get location
X        mov     cx, 512                         ; say 1 sector
X        int     DOS                             ; ask to have it done
X        jnc     WRTOK                           ; good write
X        mov     dx, offset ERMSG3               ; can't write to save file
X        mov     ah, 9
X        int     DOS                             ; tell 'em
X        mov     ah, 4Ch                         ; say terminate
X        mov     al, 3                           ; reason
X        int     DOS
X  
X        ;-------------------
X        ; Close backup file
X        ;-------------------
XWRTOK:
X        mov     ah, 3Eh                         ; say close file
X        mov     bx, BOOTHDL
X        int     DOS
X        jnc     CLOSOK                          ; closed ok
X        mov     dx, offset ERMSG4               ; can't close save file
X        mov     ah, 9
X        int     DOS                             ; tell 'em
X        mov     ah, 4Ch                         ; say terminate
X        mov     al, 4                           ; reason
X        int     DOS
X  
X        ;-----------------------------------------------------
X        ; Copy the read partition table into our sector so it
X        ; will use it when booting.
X        ;-----------------------------------------------------
XCLOSOK:
X        push    si
X        mov     si, offset DISKBUF+1BEh         ; start of partition table
X        mov     di, offset BOOTSEC+1BEh         ; ditto for new sector
X        cld                                     ; make direction positive
X        mov     cx, 4*16+2                      ; how many bytes to move
X        rep     movsb                           ; move em
X  
X        ;----------------------------------------
X        ; Write our sector back to the hard-disk
X        ;----------------------------------------
X        mov     si, 5                           ; 5 retries
XWRTBOOT:
X        push    si
X        mov     ah, 3                           ; say write to disk
X        mov     al, 1                           ; say 1 sector
X        mov     bx, offset BOOTSEC              ; point to sector to write
X        mov     cx, 1                           ; say sector 1
X        mov     dx, 80h
X        int     DISKIO                          ; do the io
X        pop     si
X        jnc     UPDOK                           ; good write to boot sector
X        dec     si                              ; count retries
X        jnz     WRTBOOT                         ; try again
X  
X        mov     dx, offset ERMSG5               ; can't write boot sector file
X        mov     ah, 9
X        int     DOS                             ; tell 'em
X        mov     ah, 4Ch                         ; say terminate
X        mov     al, 5                           ; reason
X        int     DOS
X  
X        ;----------------------------------------------------------
X        ; Inform the user that the operation finished successfully
X        ; and exit back to DOS.
X        ;----------------------------------------------------------
XUPDOK:
X        mov     dx, offset OKMSG                ; say we did it
X        mov     ah, 9
X        int     DOS                             ; tell 'em
X        mov     ah, 4Ch                         ; say terminate
X        mov     al, 0                           ; good return code
X        int     DOS
X  
X  
X  
X;****************************************************************
X;*      BOOTSEC                                                 *
X;*                                                              *
X;*      Here comes the sector patched into the hard-disk        *
X;****************************************************************
X  
XBOOTSEC:
X  
XBSTART  equ     $                               ; Start offset of our boot sector
XBOOTLOC equ     7C00h                           ; Boot sector loaded there
XBOOTSIG equ     7DFEh                           ; Boot sector signal address
XMOVETO  equ     600h                            ; Where to move it
XPARTTBL equ     BSTART + 1BEh                   ; Start of partition table in our code
X  
X  
X        cli
X        xor     ax, ax                          ; (AX) = 0
X        mov     ss, ax                          ; (SS) = Set stack segment to 0
X        mov     sp, offset BOOTLOC              ; Get boot code address
X        mov     si, sp                          ; (SI) = Source address
X        mov     es, ax                          ; (ES) = 0
X        mov     ds, ax                          ; (DS) = 0
X        sti
X        cld
X        mov     di, MOVETO                      ; (DI) = Destination address
X        mov     cx, 100h                        ; (CX) = # of words to move
X        rep     movsw                           ; Move it
X  
X        ;------------------------------------
X        ; Setup to continue the boot process
X        ;------------------------------------
X        mov     ax, MOVETO + offset RELBOOT - BSTART
X        push    ax
X        ret
X  
XRELBOOT:
X        ;----------------------------------
X        ; Set all partitions as not active
X        ;----------------------------------
X        mov     bx, MOVETO + 1BEh
X        mov     byte ptr [bx],   0
X        mov     byte ptr 16[bx], 0
X        mov     byte ptr 32[bx], 0
X        mov     byte ptr 48[bx], 0
X  
X        ;------------------------------------------
X        ; Show boot prompt 'Boot partition (1-4):'
X        ;------------------------------------------
XWRPRMPT:
X        mov     si, MOVETO + offset BOOTMSG - BSTART
X        lodsb
X        mov     cl, al
X        xor     ch, ch
XWR000:
X        lodsb
X        mov     bx, 7
X        mov     ah, 0Eh
X        int     VIDEO
X        loop    WR000
X  
X        ;-------------------------------
X        ; Get user's response & show it
X        ;-------------------------------
X        mov     ah, 0                           ; Get keyboard input
X        int     KBD
X        push    ax
X        mov     ah, 10                          ; Show it
X        mov     cx, 1
X        int     VIDEO
X        pop     ax
X  
X        ;----------------------------------
X        ; Check for legal partition number
X        ;----------------------------------
X        cmp     al, '1'                         ; # below 1 ?
X        jb      WRPRMPT                         ;  Yes, error
X        cmp     al, '4'                         ; # above 4 ?
X        ja      WRPRMPT                         ;  Yes, error
X  
X        ;--------------------------------------
X        ; AL contains partition # to boot from
X        ;--------------------------------------
X        and     al, 7                           ; Mask partition #
X  
X        ;----------------------------------------
X        ; Calculate partition table entry to use
X        ;----------------------------------------
X        mov     si, MOVETO + 1BEh               ; point to first entry
XCALCPART:
X        dec     al
X        jz      GOTPART
X        add     si, 16                          ; Advance to next partition
X        jmp     short CALCPART
X  
X  
XGOTPART:
X        ;-----------------------------------------------------
X        ; Set the requested partition as the active partition
X        ;-----------------------------------------------------
X        mov     byte ptr[si], 80h
X        push    si
X        push    bx
X        mov     ax, 0301h
X        mov     bx, MOVETO
X        mov     cx, 1
X        mov     dx, 80h
X        int     diskio
X        pop     bx
X        pop     si
X  
X        ;-------------------------------------------------------------
X        ; Now go and try to read the selected partition's boot sector
X        ;-------------------------------------------------------------
X        mov     dx, [si]                        ; (DH) = drive, (DL) = head
X        mov     cx, [si+2]                      ; (CH) = track, (CL) = sector
X        mov     bp, si                          ; Save partition pointer
X        mov     di, 5                           ; Set retry count
XRDBOOT:
X        mov     bx, BOOTLOC                     ; Location for boot
X        mov     ax, 0201h                       ; Read 1 sector
X        push    di
X        int     DISKIO                          ; Go read
X  
X        pop     di
X        jnc     GOODRD                          ; Good read
X  
X        xor     ax, ax                          ; Recalibrate
X        int     DISKIO
X        dec     di                              ; Decrement retries count
X        jnz     RDBOOT                          ; Counter at zero ?
X  
X        ;---------------------------------------------------
X        ; Can't read boot sector, show a message and hangup
X        ;---------------------------------------------------
X        mov     si, MOVETO + offset MSG2 - BSTART
XWRMSG:
X        lodsb                                   ; Get message length
X        mov     cl, al
X        xor     ch, ch
XWR002:
X        lodsb
X        mov     bx, 7
X        mov     ah, 0Eh
X        int     VIDEO
X        loop    WR002
X        jmp     WRPRMPT
X  
X  
X        ;------------------------------------------------
X        ; Boot sector read, check for the boot signature
X        ;------------------------------------------------
XGOODRD:
X        mov     si, MOVETO + offset MSG3 - BSTART       ; Point to no boot msg
X        mov     bx, BOOTSIG
X        cmp     word ptr [bx], 0AA55h           ; Check for the boot signature
X        jne     WRMSG
X  
X        ;-----------------------------------------------------------------
X        ; Finaly, go and boot.
X        ;
X        ; Before booting set:
X        ;       SI - points to partition table entry we are booting from
X        ;       BX - starting cylinder number of this partition
X        ;-----------------------------------------------------------------
X        mov     si, bp                          ; Restore partition table pointer
X  
X        mov     ax, word ptr 2[si]              ; AH-cyl, AL-sec
X        xor     bh, bh
X        mov     bl, al
X        shl     bx, 1
X        shl     bx, 1                           ; BH-2 msb bits
X        mov     bl, ah                          ; BL-8 lsb bits
X  
X        mov     ax, offset BOOTLOC              ; Where partition boot start
X        push    ax
X        ret
X  
X  
XBOOTMSG db      LMSGB, CR, LF, 'Boot partition (1-4): '
XLMSGB   equ     ($-BOOTMSG)-1
X  
XMSG2    db      LMSG2, CR, LF, 'Error loading operating system'
XLMSG2   equ     ($-MSG2)-1
X  
XMSG3    db      LMSG3, CR, LF, 'Missing operating system'
XLMSG3   equ     ($-MSG3)-1
X  
X        org     BSTART + 512
X  
XCODE    ends
X        end  WRITBOOT
X  
X  
SHAR_EOF
if test 17596 -ne "`wc -c < 'b1/mfdisk.asm'`"
then
    echo shar: error transmitting "'b1/mfdisk.asm'" '(should have been 17596 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'b2b/Makefile'" '(239 characters)'
if test -f 'b2b/Makefile'
then
    echo shar: will not over-write existing file "'b2b/Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'b2b/Makefile'
XCFLAGS=-I/usr/src/minix -Di8088
X
X#.c.s:
X#	cc $(CFLAGS) -c $*.c
X
Xall:	loader.s stack.s standalone.s main.s
X	asld -T. -s -o b2 bsu.s main.s loader.s stack.s standalone.s /usr/lib/libc.a /usr/lib/end.s > b2.sym
X	dd if=b2 of=boot bs=32 skip=1
SHAR_EOF
if test 239 -ne "`wc -c < 'b2b/Makefile'`"
then
    echo shar: error transmitting "'b2b/Makefile'" '(should have been 239 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'b2b/bsu.s'" '(5666 characters)'
if test -f 'b2b/bsu.s'
then
    echo shar: will not over-write existing file "'b2b/bsu.s'"
else
sed 's/^X//' << \SHAR_EOF > 'b2b/bsu.s'
X|
X| Second-Stage Bootstrap assembly level run-time support
X| Derrived from "tools/fsck1.s" and "kernel/klib88.s"
X|
XSTACKSIZE = 16384
X
X.globl _main, endtext, enddata, endbss
X.globl __putc, __getc, _reset_diskette, _diskio, _hd_param
X.globl csv, cret, begtext, begdata, begbss
X.globl _cylsiz, _tracksiz, _def_dev
X.globl _ds, _lcopy, _sp
X
X.text
Xbegtext:
Xstart:
X	mov	ax,cs		| ds=es=ss=cs 
X	mov	es,ax
X	mov	ds,ax
X	mov	ss,ax
X|	mov	dx,bx		| bootblok puts boot device in BX
X	xor	ax,ax
X	mov	bx,#enddata	| prepare to clear bss
X	mov	cx,#endbss
X	sub	cx,bx
X	shr	cx,*1
Xst.1:	mov	(bx),ax		| clear bss
X	add	bx,#2
X	loop	st.1
X
X	mov	_def_dev,dx
X	mov	sp,#kerstack+STACKSIZE
X	call	_main
Xst.2:	mov	bx,ax		| put scan code for '=' in bx
X|	mov	bp,#_sizes	| bp points to 'sizes' array
X	mov	sp,_ksp		| sp first 'cause we'll destroy ds
X	mov	dx,_kds
X	mov	ds,dx
X	mov	ss,dx
X	nop
X	cli
X|	mov	dx,#0x60
X|leave ES where it is so kernel can find the a.out table...
X|	mov	es,dx
X	nop
X	jmpi	0,0x60		| jmp to kernel
X
X|_exit:
X|	mov	bx,_tracksiz
X	jmp	start
X
X
X__putc:
X	xor	ax,ax
X	call	csv
X	movb	al,4(bp)	| al contains char to be printed
X	movb	ah,#14		| 14 = print char
X	movb	bl,*1		| foreground color
X	push	bp		| not preserved
X	int	0x10		| call BIOS VIDEO_IO
X	pop	bp
X	jmp	cret
X
X__getc:
X	xorb	ah,ah
X	int	0x16
X	ret
X
X_ds:
X	mov	ax,ds
X	ret
X_sp:
X	mov	ax,sp
X	ret
X
X_reset_diskette:
X	xor	ax,ax
X	call	csv
X	push	es		| not preserved
X	int	0x13		| call BIOS DISKETTE_IO
X	pop	es
X	jmp	cret
X
X
X| handle diskio(RW, sector_number, buffer, sector_count, drive) call
X| Do not issue a BIOS call that crosses a track boundary
X_diskio:
X	xor	ax,ax
X	call	csv
X	mov	tmp1,#0		| tmp1 = # sectors actually transferred
X	mov	di,10(bp)	| di = # sectors to transfer
X	mov	tmp2,di		| di = # sectors to transfer
Xd0:	mov	ax,6(bp)	| ax = sector number to start at
X	xor	dx,dx		| dx:ax is dividend
X	div	_cylsiz		| ax = cylinder, dx = sector within cylinder
X	movb	cl,ah		| cl = hi-order bits of cylinder
X	rorb	cl,#1		| BIOS expects hi bits in a funny place
X	rorb	cl,#1		| ditto
X	movb	ch,al		| cx = sector # in BIOS format
X	mov	ax,dx		| ax = sector offset within cylinder
X	xor	dx,dx		| dx:ax is dividend
X	div	_tracksiz	| ax = head, dx = sector
X	movb	dh,al		| dh = head
X	orb	cl,dl		| cl = 2 high-order cyl bits || sector
X	incb	cl		| BIOS counts sectors starting at 1
X	movb	dl,12(bp)	| dl = drive code (0-3 or 0x80 - 0x81)
X	mov	bx,8(bp)	| bx = address of buffer
X	movb	al,cl		| al = sector #
X	addb	al,10(bp)	| compute last sector
X	decb	al		| al = last sector to transfer
X	cmpb	al,_tracksiz	| see if last sector is on next track
X	jle	d1		| jump if last sector is on this track
X	mov	10(bp),#1	| transfer 1 sector at a time
Xd1:	movb	ah,4(bp)	| ah = READING or WRITING
X	addb	ah,*2		| BIOS codes are 2 and 3, not 0 and 1
X	movb	al,10(bp)	| al = # sectors to transfer
X	mov	tmp,ax		| al is # sectors to read/write
X	push	es		| BIOS ruins es
X	int	0x13		| issue BIOS call
X	pop	es		| restore es
X	cmpb	ah,*0		| ah != 0 means BIOS detected error
X	jne	d2		| exit with error
X	mov	ax,tmp		| fetch count of sectors transferred
X	xorb	ah,ah		| count is in ax
X	add	tmp1,ax		| tmp1 accumulates sectors transferred
X	mov	si,tmp1		| are we done yet?
X	cmp	si,tmp2		| ditto
X	je	d2		| jump if done
X	inc	6(bp)		| next time around, start 1 sector higher
X	add	8(bp),#0x200	| move up in buffer by 512 bytes
X	jmp	d0
Xd2:	jmp	cret
X
Xcsv:
X	pop	bx
X	push	bp
X	mov	bp,sp
X	push	di
X	push	si
X	sub	sp,ax
X	jmp	(bx)
X
Xcret:
X	lea	sp,*-4(bp)
X	pop	si
X	pop	di
X	pop	bp
X	ret
X
X|*===========================================================================*
X|*				phys_copy				     *
X|*===========================================================================*
X| This routine copies a block of physical memory.  It is called by:
X|	lcopy(destination segment, offset, source segment, offset, length)
X|    phys_copy( (long) source, (long) destination, (long) bytecount)
X
X_lcopy:
X	pushf			| save flags
X	cli			| disable interrupts
X	push bp			| save the registers
X	push ax			| save ax
X	push bx			| save bx
X	push cx			| save cx
X	push dx			| save dx
X	push si			| save si
X	push di			| save di
X	push ds			| save ds
X	push es			| save es
X	mov bp,sp		| set bp to point to saved es
X
X  L0:	mov ax,22(bp)		| ax = segment of  destination
X	mov di,24(bp)		| di = offset of destination
X	mov es,ax		| es = destination click
X
X	mov ax,26(bp)		| ax = segment of  source
X	mov si,28(bp)		| si = offset of source
X
X	mov cx,30(bp)		| cx = low-order word of byte count
X
X	mov ds,ax		| ds = source click
X
X	test cx,*0x0001		| should we copy a byte or a word at a time?
X	jz L5			| jump if even
X	rep			| copy 1 byte at a time
X	movb			| byte copy
X	jmp L6			| check for more bytes
X
X  L5:	shr cx,*1		| word copy
X	rep			| copy 1 word at a time
X	movw			| word copy
X
X  L6:	pop es			| restore all the saved registers
X	pop ds			| restore ds
X	pop di			| restore di
X	pop si			| restore si
X	pop dx			| restore dx
X	pop cx			| restore cx
X	pop bx			| restore bx
X	pop ax			| restore ax
X	pop bp			| restore bp
X	popf			| restore flags
X	ret			| return to caller
X
X| Get Hard Disk parameters
X|	hd_param(device)
X| sets sectors per track in tracksiz and returns the number of heads.
X_hd_param:
X	call	csv
X	movb	ah, #8                  | Return current drive parameters
X	movb	dl, 4(bp)               | First hard-disk
X	int	0x13
X	andb	cl, #0x3F               | discard cylinder number high bits
X 	xorb	ch, ch                  | CX - Number of sectors per track
X	mov	_tracksiz, cx
X	movb	al,dh			| cylsize = heads * tracksize
X	incb	al                      | It was 0 origin
X	xorb	ah,ah                   | AX = Number of heads
X	mul	cx
X	mov	_cylsiz, ax
X	jmp	cret
X
X.data
Xbegdata:
Xtmp:	.word 0
Xtmp1:	.word 0
Xtmp2:	.word 0
X.bss
Xbegbss:
Xkerstack:	.zerow STACKSIZE/2	| kernel stack
SHAR_EOF
if test 5666 -ne "`wc -c < 'b2b/bsu.s'`"
then
    echo shar: error transmitting "'b2b/bsu.s'" '(should have been 5666 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'MANIFEST'" '(384 characters)'
if test -f 'MANIFEST'
then
    echo shar: will not over-write existing file "'MANIFEST'"
else
sed 's/^X//' << \SHAR_EOF > 'MANIFEST'
XFile Name                 Kit Number
X--------------            ----------
XMANIFEST                     1
XREADME                       1
Xb1/bootblok.asm4             1
Xb1/fdboot.uu                 1
Xb1/hdboot.uu                 1
Xb1/mfdisk.asm                1
Xb2b/Makefile                 1
Xb2b/bsu.s                    1
Xb2b/loader.c                 2
Xb2b/main.c                   2
SHAR_EOF
if test 384 -ne "`wc -c < 'MANIFEST'`"
then
    echo shar: error transmitting "'MANIFEST'" '(should have been 384 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0