[comp.os.minix] Booting Minix from hard-disk

motti@ocsmd.ocs.com (Motti Bazar) (12/11/89)

Hi there,

After getting a lot of requests to post this, I'm posting my original
stuff again. It took me some time to find it. I assume some things
are old but even then, its usefull (no flames please). I'm in the
process of doing some new stuff. I got from Robert Hall his DOS
side development code (thanks) and wrote some utilities to fully do
all my kernel development under DOS (both the editor and compiler
under DOS are better) and even produce the Minix kernel into a DOS
file and then use another utility to boot Minix from DOS. Again,
the DOS code is Robert's and I just added the autoboot. If anybody
want more info I'll be happy to provide it.

Have fun ... Motti

uunet!ocsmd!motti


Original posting follows:


Subject: Multi-partition boot and Booting MINIX from the hard disk
==================================================================
  
Hi there,
  
After getting Minix 1.2 from PH I wanted to put it on my hard-disk.
I discovered that I could not do it. One thing that I noticed was that
in the "compatibility" file (at bugs.nosc.mil) and in the Minix docs it was
stated that it will not run on an 8MHz IBM-AT. My problem was even bigger
because not only that I have an 8MHz IBM-AT but it also uses a non
standard hard-disk (72Mb Core). I posted some questions but my mail was
broken and the answers that I got did not help alot. So, I decided to go
for it by myself. I looked on some archive sites (e.g. bugs.nosc.mil)
and found some pointers here and there.

I am posting all this thing for all of you out there that want to do the same
thing but do not want to spend the time investigating and developing all of
it. The Multi-partition boot is good even for anybody that already installed
Minix on his/her hard-disk but does not have a nice and clean way for the
Multi-partition boot. All this code can be used for other versions of Minix
(I assume) because it does not involve Minix directly but the boot code
only.

By the way, the version of Minix I got was compiled and linked for the
XT type machines so before trying it on my AT I had to install it on an
XT machine, copy at_wini.c to wini.c and recreate the system.
  
What I ended doing can be divided to 2 parts:
    1. Development of a Multi-partition boot utility.
    2. Modifications to Minix 1.2 for hard-disk booting.
  
After all this text, I included all the code needed to perform whatever
I describe here namely "mfdisk.asm" for the Multi-partition boot and
"bootblok.s" a modified version of Minix's boot block.

There are a lot more things I am going to add sometime in the future (like
using the hard-disk as root instead of the ram-disk etc.) but I decided to
post it now because its a full solution to start with and can save a lot
of time.


Part 1  -  Development of a Multi-partition boot utility
========================================================
  
I wrote a new Multi-partition utility that runs under MesSDOS and lets you
to modify the main hard-disk boot sector for booting multiple operating
systems from the same hard-disk.
This program will write a new boot sector to the first hard-disk drive that
prompts for the partition you want to boot from (1-4). To the question
'Boot partition (1-4):' you have to answer with the number of the partition
you want to boot from (1-4).
The program must be compiled as a .COM file (remember exe2bin) and run
under MesSDOS.
When the program is run, it produces a message telling you what it is going
to do. At this time you can abort it by typing <CTRL-C> or type <CR> to
allow it to modify the hard-disk.
  
Before trying to boot from multiple partitions you have to partition your
hard-disk and put the operating systems on the partitions. I used
a partitioning utility called "disk manager" from Ontrack Computer Systems.
There are other utilities available (e.g. Speedstore) but this one is a
good one.
  
After the partitioning, you can run the Multi-partition boot utility
called "mfdisk" (I started writing it with fdisk in mined and wanted to
write an fdisk clone but then I found disk manager and ended just with
whatever is there). After running the utility you are set and ready to go.
  
  
Part 2  -  Modifications to Minix 1.2 for hard-disk booting
===========================================================
  
Some of the information stated here I found in a post done by Don Dugger
(msg-id: 133@wldrdg.uucp). I had to make many more modifications especially
for standardizing the Minix boot sector without any need of the user to
understand its hard-disk parameters, edit it for defining where the boot is
etc. In this boot version I tried to be totally hard-disk independent. If
somebody will really try it, please let me know about it. Remember that for
using this boot you need to use also the Multi-partition boot process.
  
The steps for installing Minix on the hard-disk on my 8MHz IBM-AT with the
72Mb Core drives (the way I developed the boot record "bootblok.s" will
allow it to use other drives automatically) are:
  
1. The version of Minix I got was compiled and linked for the XT type
   machines so before installing it on my AT I installed it on an XT machine,
   copied at_wini.c to wini.c and recreated the system on the XT.
   Then, I copied it back to the diskettes and started working on my AT.
  
2. Partition and format the hard-disk as follows:
  
        Partition 1 - MesSDOS    -  32 Mb    (/dev/hd1)
        Partition 2 - Minix /usr -  20 Mb    (/dev/hd2)
        Partition 3 - Minix boot - 740 Kb    (/dev/hd3)
        Partition 4 - Minix /    -  17 Mb    (/dev/hd4)
  
3. Install /usr on /dev/hd2 and setup the root filesystem diskette to
   mount it automatically when booting. After this step you still have
   to boot from 2 diskettes (1. Boot 2. Root filesystem) but then you
   can use /dev/hd2 as /usr.
  
Now for the hard-disk boot:
  
4. Change a line in the file "const.h" in the "h" directory from:
  
        #define BOOT_DEV (dev_nr)  512
   to:
        #define BOOT_DEV (dev_nr)  0x304
  
5. Remake the filesystem (fs).
  
6. Modify the "build.c" program in the "tools" directory as follows:
  
   In subroutine "patch1" change the lines:
  
        ubuf[(SECTOR_SIZE/2) - 4] = sectrs + 1;
        ubuf[(SECTOR_SIZE/2) - 3] = ds;
        ubuf[(SECTOR_SIZE/2) - 2] = ip;
        ubuf[(SECTOR_SIZE/2) - 1] = cs;
   to:
        ubuf[(SECTOR_SIZE/2) - 5] = sectrs + 1;
        ubuf[(SECTOR_SIZE/2) - 4] = ds;
        ubuf[(SECTOR_SIZE/2) - 3] = ip;
        ubuf[(SECTOR_SIZE/2) - 2] = cs;
        ubuf[(SECTOR_SIZE/2) - 1] = 0xAA55;
  
   and remake the "build" program. This modifications is for setting the
   magic number in Minix's boot record.
  
7. Replace the file "bootblok.s" in the "tools" directory with the
   "bootblok.s" file included at the end of this posting and remake the
   boot block.
  
8. Run "build" as follows:
  
        build bootblok kernel mm fs init fsck /dev/hd3
  
   This will build the Minix image into "/dev/hd3" instead of to "/dev/fd0".
  
9. Put the Root filesystem diskette in the first drive and execute:
  
        cp /dev/fd0 /dev/hd4
  
   It will copy the Root filesystem diskette to /dev/hd4.
  
You are set. If you followed the instructions correctly (I hope) your
system should boot and ask you for the partition to boot from and when
you type 3 it will boot Minix from your hard-disk and load the ram-disk
from /dev/hd4.
  
Anybody trying this process, please let me know how was it, what type of
hard-disk was used and if more help is needed.


Motti (Mordehai) Bazar

uucp    : ..uunet!ocsmd!motti           snail: Online Computer Systems, Inc.
bitnet  : motti%ocsmd@uunet.uu.net             20251 Century Blvd.
internet: motti@ocsmd.uu.net  OR               Germantown, MD 20874
          bazar@gwusun.gwu.edu          vox:   (301) 428-3700

  
########################    C u t   h e r e   for    ########################
########################     m f d i s k . a s m     ########################


        page    ,132
        title   MFDISK - FDISK clone & multiple boot-record modifier
  
;------------------------------------------------------------------------------
;       This program will write a new boot sector to the first HD drive
;       that prompts for the partition you want to boot from (1-4).
;       To the question 'Boot partition (1-4):' you have to answer with
;       the number of the partition you want to boot from (1-4).
;
;       The program must be compiled as a .COM file (remember exe2bin)
;       and run under MesSDOS.
;
;       The makefile for compiling under MesSDOS should look like:
;
;           mfdisk.obj:  mfdisk.asm
;                        masm mfdisk;
;
;           mfdisk.com:  mfdisk.obj
;                        link mfdisk;
;                        exe2bin mfdisk.exe mfdisk.com
;                        del mfdisk.exe
;
;       When the program is run, it produces a message telling you what
;       it is going to do. At this time you can abort it by typing
;       <CTRL-C> or type <CR> to allow it to modify the hard-disk.
;
;       Now you can boot multiple operating systems (MesSDOS, OS/2,
;       SCO Xenix and Minix) from the same hard-disk). To do so you
;       had to partition your hard-disk to separate partitions, each
;       with another operating-system boot.
;
;           Motti (Mordehai) Bazar
;
;           uucp    : ..uunet!ocsmd!motti
;           bitnet  : motti%ocsmd@uunet.uu.net
;           internet: motti@ocsmd.uu.net  OR
;                     bazar@gwusun.gwu.edu 
;
;           snail:    Online Computer Systems, Inc.
;                     20251 Century Blvd.
;                     Germantown, MD 20874
;
;           vox:      (301) 428-3700
;
;
;       This utility is distributed for personal use only. Use it, modify it
;       or do anything you like, just live this comment and let me know of
;       any bugs or enhancements you made to it, thanks.
;
;------------------------------------------------------------------------------
  
  
;-------------------------
; First, some definitions
;-------------------------
  
VIDEO   equ     10h
KBD     equ     16h
DISKIO  equ     13h
DOS     equ     21h
  
CR      equ     0Dh
LF      equ     0Ah
  
  
;---------------------------
; Here comes the real thing
;---------------------------
  
CODE    segment byte public 'CODE'
        assume  cs:CODE, ds:CODE
  
        org     100h
  
WRITBOOT:
        jmp     START                           ; jump around
  
DISKBUF db      512 dup(?)
  
HELLOMS db      CR, LF
        db      'MFDISK - Multiple boot FDISK clone', CR, LF
        db      CR, LF
        db      'This program will read the boot sector from the first disk', CR, LF
        db      'and merge the partition table from it with the boot program', CR, LF
        db      'supplied and write it all back to the disk overlaying what', CR, LF
        db      'was there. The resultant boot program will prompt for the', CR, LF
        db      'desired partition for booting (1-4).', CR, LF
        db      CR, LF
        db      'The original boot program will be saved in a file named', CR, LF
        db      'IBMBOOT.SVE in the default directory.', CR, LF
        db      CR, LF
        db      '<CR> = continue, CONTROL-C = abort ... $'
  
CRLF    db      CR, LF, '$'
  
IBMBOOT db      'IBMBOOT.SVE',0
  
OKMSG   db      CR, LF, 'Boot sector updated', CR, LF, '$'
ERMSG1  db      CR, LF, 'Error reading boot sector', CR, LF, '$'
ERMSG2  db      CR, LF, 'Cannot open save file', CR, LF, '$'
ERMSG3  db      CR, LF, 'Cannot write save file', CR, LF, '$'
ERMSG4  db      CR, LF, 'Cannot close save file', CR, LF, '$'
ERMSG5  db      CR, LF, 'Cannot write boot sector', CR, LF, '$'
  
BOOTHDL dw      0                               ; Boot backup file handle
  
  
START:
        ;----------------------
        ; Show opening message
        ;----------------------
        mov     dx, offset HELLOMS
        mov     ah, 9
        int     DOS
  
RDCNS:
        ;---------------------------------------------------------
        ; Get user's response: <CR> or CONTROL-C (aborted by DOS)
        ;---------------------------------------------------------
        mov     ah, 0Ch
        mov     al, 1
        int     DOS
        cmp     al, CR                          ; <CR> key ?
        jne     RDCNS                           ;  No, retry
  
        ;-----------------------------------------
        ; <CR> typed, go and modify the hard-disk
        ;-----------------------------------------
        mov     dx, offset CRLF                 ; Echo <CR><LF>
        mov     ah, 9
        int     DOS
  
        ;------------------------------------
        ; Read the sector from the hard-disk
        ;------------------------------------
        mov     si, 5                           ; Retry for 5 times
RDDSK:
        push    si                              ; Save retry counter
        mov     ah, 2                           ; Read disk
        mov     al, 1                           ; 1 sector
        mov     bx, offset DISKBUF              ; Point to buffer
        mov     ch, 0                           ; Cylinder 0
        mov     cl, 1                           ; Sector 1
        mov     dh, 0                           ; Track 0
        mov     dl, 80h                         ; Harddisk 0
        int     DISKIO
        pop     si
        jnc     RDOK                            ; Good read
        dec     si                              ; More tries?
        jnz     RDDSK                           ;  Yes, try again
        mov     dx, offset ERMSG1               ;  No, point to trouble message
        mov     ah, 9                           ; say console write
        int     DOS                             ; can't read boot sector
        mov     ah, 4Ch                         ; say terminate
        mov     al, 1                           ; error return code
        int     DOS
  
        ;---------------------------------
        ; Create the file to save it into
        ;---------------------------------
RDOK:
        mov     dx, offset IBMBOOT              ; get file name
        mov     ah, 3Ch                         ; say create it
        sub     cx, cx                          ; zero attribute
        int     DOS
        jnc     OPENOK                          ; file opened
        mov     dx, offset ERMSG2               ; can't open save file
        mov     ah, 9
        int     DOS                             ; tell 'em
        mov     ah, 4Ch                         ; say terminate
        mov     al, 2                           ; reason
        int     DOS
  
        ;---------------------------------
        ; Write sector to the backup file
        ;---------------------------------
OPENOK:
        mov     BOOTHDL, ax                     ; save handle
        mov     bx, ax                          ; and put in bx
        mov     ah, 40h                         ; say write to file
        mov     dx, offset DISKBUF              ; get location
        mov     cx, 512                         ; say 1 sector
        int     DOS                             ; ask to have it done
        jnc     WRTOK                           ; good write
        mov     dx, offset ERMSG3               ; can't write to save file
        mov     ah, 9
        int     DOS                             ; tell 'em
        mov     ah, 4Ch                         ; say terminate
        mov     al, 3                           ; reason
        int     DOS
  
        ;-------------------
        ; Close backup file
        ;-------------------
WRTOK:
        mov     ah, 3Eh                         ; say close file
        mov     bx, BOOTHDL
        int     DOS
        jnc     CLOSOK                          ; closed ok
        mov     dx, offset ERMSG4               ; can't close save file
        mov     ah, 9
        int     DOS                             ; tell 'em
        mov     ah, 4Ch                         ; say terminate
        mov     al, 4                           ; reason
        int     DOS
  
        ;-----------------------------------------------------
        ; Copy the read partition table into our sector so it
        ; will use it when booting.
        ;-----------------------------------------------------
CLOSOK:
        push    si
        mov     si, offset DISKBUF+1BEh         ; start of partition table
        mov     di, offset BOOTSEC+1BEh         ; ditto for new sector
        cld                                     ; make direction positive
        mov     cx, 4*16+2                      ; how many bytes to move
        rep     movsb                           ; move em
  
        ;----------------------------------------
        ; Write our sector back to the hard-disk
        ;----------------------------------------
        mov     si, 5                           ; 5 retries
WRTBOOT:
        push    si
        mov     ah, 3                           ; say write to disk
        mov     al, 1                           ; say 1 sector
        mov     bx, offset BOOTSEC              ; point to sector to write
        mov     cx, 1                           ; say sector 1
        mov     dx, 80h
        int     DISKIO                          ; do the io
        pop     si
        jnc     UPDOK                           ; good write to boot sector
        dec     si                              ; count retries
        jnz     WRTBOOT                         ; try again
  
        mov     dx, offset ERMSG5               ; can't write boot sector file
        mov     ah, 9
        int     DOS                             ; tell 'em
        mov     ah, 4Ch                         ; say terminate
        mov     al, 5                           ; reason
        int     DOS
  
        ;----------------------------------------------------------
        ; Inform the user that the operation finished successfully
        ; and exit back to DOS.
        ;----------------------------------------------------------
UPDOK:
        mov     dx, offset OKMSG                ; say we did it
        mov     ah, 9
        int     DOS                             ; tell 'em
        mov     ah, 4Ch                         ; say terminate
        mov     al, 0                           ; good return code
        int     DOS
  
  
  
;****************************************************************
;*      BOOTSEC                                                 *
;*                                                              *
;*      Here comes the sector patched into the hard-disk        *
;****************************************************************
  
BOOTSEC:
  
BSTART  equ     $                               ; Start offset of our boot sector
BOOTLOC equ     7C00h                           ; Boot sector loaded there
BOOTSIG equ     7DFEh                           ; Boot sector signal address
MOVETO  equ     600h                            ; Where to move it
PARTTBL equ     BSTART + 1BEh                   ; Start of partition table in our code
  
  
        cli
        xor     ax, ax                          ; (AX) = 0
        mov     ss, ax                          ; (SS) = Set stack segment to 0
        mov     sp, offset BOOTLOC              ; Get boot code address
        mov     si, sp                          ; (SI) = Source address
        mov     es, ax                          ; (ES) = 0
        mov     ds, ax                          ; (DS) = 0
        sti
        cld
        mov     di, MOVETO                      ; (DI) = Destination address
        mov     cx, 100h                        ; (CX) = # of words to move
        rep     movsw                           ; Move it
  
        ;------------------------------------
        ; Setup to continue the boot process
        ;------------------------------------
        mov     ax, MOVETO + offset RELBOOT - BSTART
        push    ax
        ret
  
RELBOOT:
        ;----------------------------------
        ; Set all partitions as not active
        ;----------------------------------
        mov     bx, MOVETO + 1BEh
        mov     byte ptr [bx],   0
        mov     byte ptr 16[bx], 0
        mov     byte ptr 32[bx], 0
        mov     byte ptr 48[bx], 0
  
        ;------------------------------------------
        ; Show boot prompt 'Boot partition (1-4):'
        ;------------------------------------------
WRPRMPT:
        mov     si, MOVETO + offset BOOTMSG - BSTART
        lodsb
        mov     cl, al
        xor     ch, ch
WR000:
        lodsb
        mov     bx, 7
        mov     ah, 0Eh
        int     VIDEO
        loop    WR000
  
        ;-------------------------------
        ; Get user's response & show it
        ;-------------------------------
        mov     ah, 0                           ; Get keyboard input
        int     KBD
        push    ax
        mov     ah, 10                          ; Show it
        mov     cx, 1
        int     VIDEO
        pop     ax
  
        ;----------------------------------
        ; Check for legal partition number
        ;----------------------------------
        cmp     al, '1'                         ; # below 1 ?
        jb      WRPRMPT                         ;  Yes, error
        cmp     al, '4'                         ; # above 4 ?
        ja      WRPRMPT                         ;  Yes, error
  
        ;--------------------------------------
        ; AL contains partition # to boot from
        ;--------------------------------------
        and     al, 7                           ; Mask partition #
  
        ;----------------------------------------
        ; Calculate partition table entry to use
        ;----------------------------------------
        mov     si, MOVETO + 1BEh               ; point to first entry
CALCPART:
        dec     al
        jz      GOTPART
        add     si, 16                          ; Advance to next partition
        jmp     short CALCPART
  
  
GOTPART:
        ;-----------------------------------------------------
        ; Set the requested partition as the active partition
        ;-----------------------------------------------------
        mov     byte ptr[si], 80h
        push    si
        push    bx
        mov     ax, 0301h
        mov     bx, MOVETO
        mov     cx, 1
        mov     dx, 80h
        int     diskio
        pop     bx
        pop     si
  
        ;-------------------------------------------------------------
        ; Now go and try to read the selected partition's boot sector
        ;-------------------------------------------------------------
        mov     dx, [si]                        ; (DH) = drive, (DL) = head
        mov     cx, [si+2]                      ; (CH) = track, (CL) = sector
        mov     bp, si                          ; Save partition pointer
        mov     di, 5                           ; Set retry count
RDBOOT:
        mov     bx, BOOTLOC                     ; Location for boot
        mov     ax, 0201h                       ; Read 1 sector
        push    di
        int     DISKIO                          ; Go read
  
        pop     di
        jnc     GOODRD                          ; Good read
  
        xor     ax, ax                          ; Recalibrate
        int     DISKIO
        dec     di                              ; Decrement retries count
        jnz     RDBOOT                          ; Counter at zero ?
  
        ;---------------------------------------------------
        ; Can't read boot sector, show a message and hangup
        ;---------------------------------------------------
        mov     si, MOVETO + offset MSG2 - BSTART
WRMSG:
        lodsb                                   ; Get message length
        mov     cl, al
        xor     ch, ch
WR002:
        lodsb
        mov     bx, 7
        mov     ah, 0Eh
        int     VIDEO
        loop    WR002
        jmp     WRPRMPT
  
  
        ;------------------------------------------------
        ; Boot sector read, check for the boot signature
        ;------------------------------------------------
GOODRD:
        mov     si, MOVETO + offset MSG3 - BSTART       ; Point to no boot msg
        mov     bx, BOOTSIG
        cmp     word ptr [bx], 0AA55h           ; Check for the boot signature
        jne     WRMSG
  
        ;-----------------------------------------------------------------
        ; Finaly, go and boot.
        ;
        ; Before booting set:
        ;       SI - points to partition table entry we are booting from
        ;       BX - starting cylinder number of this partition
        ;-----------------------------------------------------------------
        mov     si, bp                          ; Restore partition table pointer
  
        mov     ax, word ptr 2[si]              ; AH-cyl, AL-sec
        xor     bh, bh
        mov     bl, al
        shl     bx, 1
        shl     bx, 1                           ; BH-2 msb bits
        mov     bl, ah                          ; BL-8 lsb bits
  
        mov     ax, offset BOOTLOC              ; Where partition boot start
        push    ax
        ret
  
  
BOOTMSG db      LMSGB, CR, LF, 'Boot partition (1-4): '
LMSGB   equ     ($-BOOTMSG)-1
  
MSG2    db      LMSG2, CR, LF, 'Error loading operating system'
LMSG2   equ     ($-MSG2)-1
  
MSG3    db      LMSG3, CR, LF, 'Missing operating system'
LMSG3   equ     ($-MSG3)-1
  
        org     BSTART + 512
  
CODE    ends
        end  WRITBOOT
  
  
########################    C u t   h e r e   for    ########################
########################     b o o t b l o k . s     ########################
  
  
|----------------------------------------------------------------------------
|
| This is a modified version of the Minix bootblok.s file. It supports the
| boot of the operating system (Minix 1.2) from the hard-disk.
| I found some of this code in one of the postings but it had problems
| like its inability to boot from non-standard high capacity disks
| (my Core 72Mb disk has 9 heads) and the need to setup it up with the
| cylinder number and sectors/track.
| The way I built it is that the starting cylinder number is passed
| automatically from the main boot code (you have to use my Multi-partition
| boot code to support it) and in the beginning I inquire the type of disk
| and use it instead of hardcoding it into the code.
|
| The other change (here and in build) is to support the magic number
| at the end of the boot sector. My multi-partition boot utility sets
| the main boot sector to check for it when trying to load the requested
| boot sector from the partition requested to be boot from.
|
| Have fun.....
|
|           Motti (Mordehai) Bazar
|
|           uucp    : ..uunet!ocsmd!motti
|           bitnet  : motti%ocsmd@uunet.uu.net
|           internet: motti@ocsmd.uu.net  OR
|                     bazar@gwusun.gwu.edu 
|
|           snail:    Online Computer Systems, Inc.
|                     20251 Century Blvd.
|                     Germantown, MD 20874
|
|           vox:      (301) 428-3700
|
|
| When the PC is powered on, it reads the first block from the floppy
| disk into address 0x7C00 and jumps to it.  This boot block must contain
| the boot program in this file.  The boot program first copies itself to
| address 192K - 512 (to get itself out of the way).  Then it loads the
| operating system from the boot diskette into memory, and then jumps to
| fsck.
| Loading is not trivial because the PC is unable to read a track into
| memory across a 64K boundary, so the positioning of everything is critical.
| The number of sectors to load is contained at address 502 of this block.
| The value is put there by the build program after it has discovered how
| big the operating system is.  When the bootblok program is finished
| loading,it jumps indirectly to the program (fsck) which address is given
| by the last 2 words in the boot block.
|
| Summary of the words patched into the boot block by build:
|
| Word at 502: # sectors to load
| Word at 504: # DS value for fsck
| Word at 506: # PC value for fsck
| Word at 508: # CS value for fsck
| Word at 510: Magic boot block #
|
| This version of the boot block must be assembled without separate I & D
| space.
|
|----------------------------------------------------------------------------
  
        BIOSSEG = 0x07C0        | Boot block is loaded here
        BOOTSEG = 0x2FE0        | Boot block is copied there (192K-512b)
        DSKBASE = 120           | 120 = 4 * 0x1E = ptr to disk parameters
  
final   = 502
fsck_ds = 504
fsck_pc = 506
fsck_cs = 508
magic   = 510
  
.globl begtext, begdata, begbss, endtext, enddata, endbss  | asld needs these
.text
begtext:
.data
begdata:
.bss
begbss:
.text
  
        |---------------------------------------------------------------
        | My Multi-partition boot code sets BX as the starting cylinder
        | of the partition we are booting from. Save it for use.
        |---------------------------------------------------------------
        mov     ax, #BIOSSEG
        mov     ds, ax
        mov     startcyl, bx
  
        |---------------------------
        | copy bootblock to bootseg
        |---------------------------
        xor     si, si                  | (DS:SI) = point to original block
        mov     ax, #BOOTSEG
        mov     es, ax
        xor     di, di                  | (ES:DI) = point to new block
        mov     cx, #256                | # of words to move
        rep
        movw                            | Copy loop
  
        |----------------------
        | start boot procedure
        |----------------------
        jmpi    start, BOOTSEG          | (CS) = BOOTSEG, continue execution
  
start:
        mov     dx, cs
        mov     ds, dx                  | (DS) = (CS)
        mov     ss, dx                  | (SS) = (CS) [stack in high core]
        mov     sp, #1536               | Initialize SP to high core
        xor     ax, ax
        mov     es, ax                  | (ES) = 0
  
        |----------------------------
        | initialize disk parameters
        |----------------------------
        mov     ax, #atpar              | tenatively assume 1.2M diskette
        seg     es
        mov     DSKBASE, ax
        seg     es
        mov     DSKBASE+2, dx
  
        |----------------
        | print greeting
        |----------------
        mov     ax, #2                  | reset video
        int     0x10
        mov     ax, #0x0200             | Put cursor in upper-left corner
        xor     bx, bx
        xor     dx, dx
        int     0x10
        mov     bx, #greet              | Show greeting msg
        call    print
  
        |---------------------
        | Set disk parameters
        |---------------------
        movb    ah, #8                  | Return current drive parameters
        movb    dl, #0x80               | First hard-disk
        int     0x13
        andb    cl, #0x3F               | discard cylinder number high bits
        xorb    ch, ch                  | CX - Number of sectors per track
        mov     tracksiz, cx
        movb    dl, dh
        incb    dl                      | It was 0 origin
        xorb    dh, dh                  | DX = Number of heads
        mov     nheads, dx
  
        |-----------------------------------------
        | Load the operating system from diskette
        |-----------------------------------------
load:
        call    setreg                  | set up ah, cx, dx
  
        |-------------------------------------------------------------------
        | Calculate start address in memory to load data into:
        | "disksec" is 1 in the beginning, each sector is 512 bytes.
        | The beginning address to start load into is 1536 (512*3) so
        | in memory we start with the disk sector + 2.
        | We have to multiply the sector number by 512 to get the physical
        | address (shl 9) but if we use it for the segment we need
        | to shift it (9-4) 5 times only.
        |-------------------------------------------------------------------
        mov     bx, disksec             | BX = number of next sector to read
        add     bx, #2
        shl     bx, #1
        shl     bx, #1
        shl     bx, #1
        shl     bx, #1
        shl     bx, #1
        mov     es, bx                  | (ES:BX) = core address (BX = 0)
        xor     bx, bx
  
        add     disksec, ax             | AX = how many sectors to read
        orb     cl, xtra                | cylinder high bits
        movb    ah, #2                  | opcode for read
        int     0x13                    | call the BIOS for a read
        jb      error                   | jump on diskette error
        mov     ax, disksec             | see if we are done loading
        cmp     ax, final               | ditto
        jb      load                    | jump if there is more to load
  
        |---------------------------
        | Loading done.  Finish up.
        |---------------------------
        cli
        mov     bx, tracksiz            | fsck expects # sectors/track in bx
        mov     ax, fsck_ds             | set segment registers
        mov     ds, ax                  | when sep I&D DS != CS
        mov     es, ax                  | otherwise they are the same.
        mov     ss, ax                  | words 504 - 510 are patched by build
  
        seg     cs
        jmpi    @fsck_pc                | jmp to fsck
  
  
        |-------------------------------------------------------------------
        |       SETREG
        |
        |       Given the number of the next disk block to read, disksec,
        |       compute the cylinder, sector, head, and number of sectors
        |       to read as follows:
        |
        |               DL   - Hard-disk drive number
        |               DH   - Head number
        |               CH   - Cylinder to read
        |               CL   - Sector number
        |               xtra - high 2 bits of cylinder
        |               AL   - # of sectors to read
        |-------------------------------------------------------------------
setreg:
        |--------------------------------------------
        | Divide Start-sector-# by Sectors-per-track
        |--------------------------------------------
        mov     si, tracksiz            | SI = Sectors per track
        mov     ax, disksec             | AX = next sector to read
        xor     dx, dx                  | DX:AX = 32-bit start sector number
        div     si                      | divide sector # by track size
                                        |      AX-logical track no
                                        |      DX-sector # (0-origin)
  
        mov     cx, ax                  | CX = logical track #
        mov     bx, dx                  | BX = sector number (0-origin)
  
        mov     ax, disksec             | AX = next sector to read
        add     ax, si                  | ax = last sector to read + 1
        dec     ax                      | ax = last sector to read
        xor     dx, dx                  | DX:AX = 32-bit dividend
        div     tracksiz                | divide last sector by track size
  
        cmpb    al, cl                  | is starting track = ending track
        je      set1                    | jump if whole read on 1 cylinder
        sub     si, dx                  | compute lower sector count
        dec     si                      | si = # sectors to read
  
        |-----------------------------------------------------------------
        | Check to see if this read crosses a 64K boundary (128 sectors).
        | Such calls must be avoided.  The BIOS gets them wrong.
        |-----------------------------------------------------------------
set1:
        mov     ax, disksec             | ax = next sector to read
        add     ax, #2                  | disk sector 1 goes in core sector 3
        mov     dx, ax                  | dx = next sector to read
        add     dx, si                  | dx = one sector beyond end of read
        dec     dx                      | dx = last sector to read
        shl     ax, #1                  | ah = which 64K bank does read start at
        shl     dx, #1                  | dh = which 64K bank foes read end in
        cmpb    ah, dh                  | ah != dh means read crosses 64K boundary
        je      set2                    | jump if no boundary crossed
        shrb    dl, #1                  | dl = excess beyond 64K boundary
        xorb    dh, dh                  | dx = excess beyond 64K boundary
        sub     si, dx                  | adjust si
        dec     si                      | si = number of sectors to read
  
set2:
        |-----------------------
        | Calculate head number
        |-----------------------
        push    si
        mov     si, nheads              | SI = Number of heads
        mov     ax, cx
        xor     dx, dx                  | DX:AX = 32-bit logical start track
        div     si                      | divide logical track # by # of heads
                                        |    AX-# of cylinders from beginning of partition
                                        |    DX-head
        movb    dh, dl                  | (DH) = head number
        pop     si
        movb    dl, #0x80               | (DL) = driver number (80=hd)
  
        mov     cx, ax
        add     cx, startcyl            | low cylinder for boot partition
  
        push    cx
        xorb    cl, cl
        shr     cx, #1
        shr     cx, #1                  | excess cylinder goes into cl (high 2 bits)
        movb    xtra, cl                | xtra - high 2 bits of cylinder
        pop     cx
  
        movb    ch, cl                  | (CH) = Cylinder #
  
        movb    cl, bl                  | (cl) = sector number (0-origin)
        incb    cl                      | (CL) = sector number (1-origin)
  
        mov     ax, si                  | (AX) = Number of sectors to read
  
        ret                             | return values in ax, cx, dx
  
  
        |------------------------------
        |       ERROR
        |
        |       error & print routines
        |------------------------------
error:
        push    ax
        mov     bx, #fderr
        call    print                   | print msg
        xor     cx, cx
err1:
        mul     0                       | delay
        loop    err1
        int     0x19
  
  
        |------------------------------------
        |       PRINT
        |
        |       Print a string pointed by BX
        |------------------------------------
print:
        movb    al, (bx)                | AL = Character to be printed
        testb   al, al                  | null char?
        jne     prt1                    | no
        ret                             | else return
prt1:
        movb    ah, *14                 | 14 = print char
        inc     bx                      | increment string pointer
        push    bx                      | save bx
        movb    bl, *1                  | foreground color
        xorb    bh, bh                  | page 0
        int     0x10                    | call BIOS VIDEO_IO
        pop     bx                      | restore bx
        jmp     print                   | next character
  
  
  
disksec:        .word   1               | Next sector to read
xtra:           .byte   0               | 2 msb of cylinder number
startcyl:       .word   0               | Partition start cylinder
tracksiz:       .word   0               | Sectors per Track
nheads:         .word   0               | Number of heads
pcpar:          .byte   0xDF, 0x02, 25, 2, 9, 0x2A, 0xFF, 0x50, 0xF6, 1, 3   | for PC
atpar:          .byte   0xDF, 0x02, 25, 2,15, 0x1B, 0xFF, 0x54, 0xF6, 1, 8   | for AT
  
fderr:          .asciz  "Read error, Rebooting...\r\n"
greet:          .asciz  "\rBooting MINIX 1.2 (HD v1.00)\r\n"
  
  
        |------------------------------------------------------------
        | Don't forget that words 502 - 510 are filled in by build.
        | The regular code had better not get that far.
        |------------------------------------------------------------
.text
endtext:
.data
enddata:
.bss
endbss: