masterboot.s
Skip to line: 1050 - 1100 - 1150 - 1200 - 1250 - 1281


Highlighted entries were made in the last day
Select a different time increment to highlight entries
Current GMT time: Jul 23 2008 21:45:46

If you have a comment for masterboot.s, please click here.
Name: sushil MayengbamEmail:  memsana.sushil@gmail.comDate: Jul 21 2008 18:13:31 GMT
Subject:  1193:1194
Reponse: we need to reset lowsec(absolute sector number to be read) because this would be the MBR and from its partition table, we'll read the first sector from the sub-partition (which was pushed into the stack before coming into this code)
 
Respond to sushil Mayengbam's comment.
 
 
Name: sushil MayengbamEmail:  memsana.sushil@gmail.comDate: Jul 20 2008 18:55:33 GMT
Subject:  line 1065:1066
Reponse: We push the si because when we ret after loading the bootblock, the eip will be pointing to LOADOFF at the same time the sp will also be pointing to it automatically.
 
Respond to sushil Mayengbam's comment.
 
 
Name: leeEmail:  lemondaya@yahoo.com.cnDate: Oct 10 2006 03:34:43 GMT
Subject:  my problem
Reponse: This is my first time to touch minix,It is hard for me to understand. But your explainations help me a lot. Thank you very much.
If it is convienient for you,can I ask you some questions in the coming day if i have some.
 
Respond to lee's comment.
 
 
1000   !       masterboot 1.9 - Master bootblock code         Author: Kees J. Bot
1001   !       modified to support drives on 2nd IDE port -- asw 2000-01-23
Expand/Collapse Item1002   !
An exclamation mark (!) indicates a comment.  The assembler ignores everything to the right of an exclamation point.

Before going any further, read the first 4 paragraphs in section 2.5.2 and read the entire 2.6.5 section of Operating Systems by Andrew Tanenbaum and Albert Woodhull.  Haven't bought the book?  You won't be able to get through this web site without buying the book - so buy the book.  I won't be going over things that the book already discusses.

Expand/Collapse Item1003   ! This code may be placed in the first sector(the boot sector) of a floppy,
Expand/Collapse Item1004   ! hard disk or hard disk primary partition. There it will perform the
Expand/Collapse Item1005   ! following actions at boot time:
The code below checks to see if this code was loaded from a floppy; however, I don't understand why a master boot record would ever be put on a floppy.  You typically do not partition a floppy.  In the third paragraph of section 2.6.5, Tanenbaum and Woodhull discuss a circumstance in which a floppy might be partitioned but indicate that even under this circumstance, a master boot record would not exist on the floppy.  Also, the comment on line 1151 suggests the same.  If anyone can see a point to having a master boot record on a floppy, please submit a comment to the site which will be displayed below.
Name: Jeff ZhaoEmail:  jeff_z@126.comDate: Jul 27 2006 14:26:25 GMT
Subject:  Thanx!
Reponse: Hello, guys! I am really appreciate that the webmaster give us such a fabulance thing. I hope more people who are crazy about Minix could join us and share their idea with us. I'll pay more attention to this site and give my comments if my assignment could be done in time.
 
Respond to Jeff Zhao's comment.
 
 
Name: Steven DimitrovEmail:  stf_dimitrov@mail.bgDate: Jul 02 2004 14:13:52 GMT
Subject:  MBR on floppy
Reponse: We could put MBR /masterboot.s/ on floppy to preserve our original MBR on the hard disk. It does not matter that floppy does not have partitions because this code never checks Partition Table in the case it came from floppy and variable "fix" is 0.
In this scenario the first sector from the second floppy will be loaded /eventually bootblock.s/. because "load0" procedure will be called with dl=1 !!! Follow the code and you will see how the value of dl-register is used.

Name: sushil MayengbamEmail:  memsana.sushil@gmail.comDate: Jul 20 2008 18:37:20 GMT
Subject: Re: MBR on floppy
Reponse: I like to believe that this code (masterboot.s) can also come from the floppy. When the BIOS loads this code from say, floppy, with dl = 0, it'll load the bootblock.s from the next floppy-drive (by dl = 1).This is shown in the nextdisk: (1171) when this code is loaded from the floppy disk.
 
 Continue discussion.
 
 
1006   !
1007   ! - If the ALT key is held down, then '/dev/hd?' is typed and you are
Expand/Collapse Item1008   !   expected to type a number key (0 - 9) to select the device to boot
Expand/Collapse Item1009   !   on primary IDE controller, or an alpha key (a - j) to select a boot
Expand/Collapse Item1010   !   device on the secondary controller (a=hd10, b=hd11, ... f=hd15, etc).
hd0 is the entire first hard drive, hd1 is the first partition on that hard drive, hd2 is the second, hd3 is the third and hd4 is the fourth.  hd5 is the entire second hard drive and hd6-hd9 are the partitions on that drive.  hd10 is the third hard drive and hd11-hd14 are the partitions on that drive and hd15 is the fourth hard drive and hd16-hd19 are the partitions on that drive.  Within each partition there can be four further subpartitions.  hd1a is the first subpartition within hd1, hd1b is the second subpartition, hd1c is the third and hd1d is the fourth.

If a drive is partitioned, there must be 4 partitions.  If a partition is subpartitioned, there must be 4 subpartitions.  Any partition or subpartition may have a size of 0 but there must be 4 partitions or subpartitions.

Note that a partition can be specified after hitting the ALT key but a subpartition cannot be specified.  For example, if subpartitions hd3b and hd3c are both bootable, there's no way of specifying either one after hitting the ALT key.  (You could use the installboot utility program to mark one of the subpartitions as active but that takes a little more effort.)

1011   !
Expand/Collapse Item1012   ! - If locked into booting a certain partition, then do so.
See line 1053 for an explanation of this comment.
1013   !
1014   ! - If the booted device is a hard disk and one of the partitions is active
1015   !   then the active partition is booted.
1016   !
1017   ! - Otherwise the next floppy or hard disk device is booted, trying them one
1018   !   by one.
1019   !
1020   ! To make things a little clearer, the boot path might be:
Expand/Collapse Item1021   !       /dev/fd0        - Floppy disk containing data, tries fd1 then hd0
Older machines are likely to halt the process until you remove the floppy.
1022   !       [/dev/fd1]      - Drive empty
1023   !       /dev/hd0        - Master boot block, selects active partition 3
1024   !       /dev/hd3        - Submaster, selects active subpartition 1
Expand/Collapse Item1025   !       /dev/hd3a       - Minix bootblock, reads secondary boot code /boot
The code found in the bootblock.s file is called the bootstrap.
Expand/Collapse Item1026   !       Minix           - Started by secondary boot from /minix
If a hard drive partition (as the book describes in section 2.6.5) is booted, the sequence is master boot (this code), bootstrap, boot monitor and finally the minix operating system.  If a hard drive subpartition is booted, the sequence is master boot, master boot (again), bootstrap, boot monitor and finally the minix operating system.
Expand/Collapse Item1027
The "0x" indicates that the value is in hexadecimal notation.  If you are unfamiliar with the term "hexadecimal," look at this site.

The first instruction of this code (the jmp instruction on line 1052) is loaded at an offset of 0x7C00 into memory.

The figure below shows the memory layout.  This code is initially loaded at memory address LOADOFF (0x7C00) but then copied to memory address BUFFER (0x0600).  The code jmp 's there to make room for the next block we'll load, which will either be another master boot block or a bootstrap (as found in bootblock.s).

Although you won't find it explicitly in this code or in bootblock.s, both the master boot blocks and boot blocks on disk have the magic number at an offset of 510.  How'd they get there?  The installboot utility is responsible for patching in the values.  Go to this link  for the master boot and this link  for the boot block.  These links show where SIGNATURE (0xAA55, the magic number) is patched into the master boot blocks and boot blocks at MAGIC (which is the same value as installboot's SIGPOS).  Don't spend too much time studying the installboot.c code.  It is only important that you begin to understand the role that the installboot utility plays.

1028           LOADOFF    =    0x7C00  ! 0x0000:LOADOFF is where this code is loaded
1029           BUFFER     =    0x0600  ! First free memory
1030           PART_TABLE =       446  ! Location of partition table within this code
1031           PENTRYSIZE =        16  ! Size of one partition table entry
1032           MAGIC      =       510  ! Location of the AA55 magic number
1033
Expand/Collapse Item1034  ! <ibm/partition.h>:
Expand/Collapse Item1035            bootind    =         0
Expand/Collapse Item1036            sysind     =         4
Expand/Collapse Item1037            lowsec     =         8
1038
1039
Expand/Collapse Item1040    .define begtext, begdata, begbss, endtext, enddata, endbss, _main
Expand/Collapse Item1041    .data
Expand/Collapse Item1042    begdata:
Expand/Collapse Item1043    .bss
Expand/Collapse Item1044    begbss:
Expand/Collapse Item1045    .text
Expand/Collapse Item1046    begtext:
Expand/Collapse Item1047    _main:
There are 3 main assembler files in the boot sequence (masterboot.s, bootblock.s, and boothead.s ) and only 2 of the files .define begtext, begdata, and begbss and only masterboot.s (this file).defines endtext, enddata, endbss, and _main.  The convention used in bootblock.s  is the simplest - bootblock.s begins text (i.e. code) sections with .text, data sections with .data, and (if it had a bss section) bss sections with .bss but does not .define begtext,begdata, begbss, endtext, enddata, endbss, and _main.

If anyone sees a point to the extra .defines (begtext, begdata, etc.), please submit a comment to the site which will be displayed below.

(The bss section holds uninitialized global variables; the bss section is discussed later.)

1048
1049   ! Find active (sub)partition, load its first sector, run it.
1050
1051   master:
1052           jmp     over
Expand/Collapse Item1053    fix:    .data1  0                       ! If 1-9 then always boot that device
.data1 reserves 1 byte of memory at the given address (in this case, fix).  This memory address is initialized to a value of zero (0).  If this value is anything other than 0, we are "locked" into booting the specific partition.  (See line 1012 above).  How do we change the value of fix? Again, this is a responsibility of the installboot utility.

Why does data immediately follow the first instruction?  Directly after the first instruction is a convenient place to stick the data.  You'll see this trick elsewhere also.  Look at line 06051 in the book.  This is the first instruction of the minix kernel.

1054   over:
Expand/Collapse Item1055            xor     ax, ax
Expand/Collapse Item1056            mov     ds, ax
Expand/Collapse Item1057            mov     es, ax
The first instruction zeroes the ax register (any number xor'ed with itself is zero).  This is a pretty common practice.  The instruction

mov ax, #0

is slower and takes up 3 bytes compared with xor's 2 bytes.

One thing that initially confuses people with assembler is the order of the operands.  The syntax of the mov instruction is:

mov destination, source

This seems a little strange to me (probably because this is not consistent with the syntax of the Unix cp command) but most assemblers use this syntax. 

Expand/Collapse Item1058            cli
Expand/Collapse Item1059            mov     ss, ax                  ! ds = es = ss = Vector segment
Expand/Collapse Item1060            mov     sp, #LOADOFF
Expand/Collapse Item1061            sti
If you mov a value into the stack register (ss) or the stack pointer (sp), disable the interrupts first.  The ss and sp registers hold the address to which the interrupt will return after its completion.  If the ss and sp register are in flux, you have no idea where the code will return.

The interrupts are disabled with the cli (clear interrupts) instruction and reenabled with the sti (set interrupts) instruction.

What's the pound sign (#) all about?  The pound sign indicates that the value of LOADOFF rather than the contents of the memory location LOADOFF is mov'ed into the register.

Expand/Collapse Item1062            mov     bp, #BUFFER+PART_TABLE  ! Often used address
bp is used here as a general purpose register.  The value of bp doesn't change in this code.
1063
Expand/Collapse Item1064    ! Copy this code to safety, then jump to it.
The figure in the comments of line 1027 describes copying this code from LOADOFF to BUFFER and then jmp'ing there.  This is accomplished in lines 1065-1073.
1065           mov     si, sp                  ! si = start of this code
Expand/Collapse Item1066            push    si                      ! Also its return address
This line is important later in the code.  The ret instruction on lines 1161, 1183, and 1243  jumps to LOADOFF, which is where either another master boot block or a boot block will have been loaded.
1067           mov     di, #BUFFER             ! Buffer area
Expand/Collapse Item1068            mov     cx, #512/2              ! One sector
Since the rep movs instruction moves cx words (not bytes) from ds:si (which is 0:LOADOFF) to es:di (which is 0:BUFFER), the number of bytes is divided by 2.  (The size of a word is architecture dependent.  On a 16-bit architecture - like real-mode on the 80x86's - 2 bytes=1 word and on a 32-bit architecture - like protected mode on the 80x86's - 4 bytes=1 word.  Since the processor is in real mode during the boot sequence and switches to protected mode (if the minix kernel has been compiled for protected mode) immediately before jumping to the kernel, 2 bytes=1 word.  Note that word is sometimes used to mean 2 bytes, regardless of the architecture.  )
Expand/Collapse Item1069            cld
cld (clear direction flag) specifies that the rep movs instruction copies the bytes from 0:LOADOFF to 0:LOADOFF+512, not the bytes from 0:LOADOFF to 0:LOADOFF-512.  If the latter is desired, use std (set direction flag) instead of cld.
1070           rep
1071           movs
Expand/Collapse Item1072            jmpf    BUFFER+migrate, 0       ! To safety
jmpf (far jump) obtains a new segment (in this case 0) and a new offset (BUFFER+migrate).  Even though movb ah, #0x02 is the next instruction executed, this instruction is located LOADOFF-BUFFER bytes lower in memory.
1073   migrate:
1074
Expand/Collapse Item1075    ! ALT key pressed to override active device boot?
Expand/Collapse Item1076    key:
Expand/Collapse Item1077            movb    ah, #0x02               ! Keyboard shift status
Expand/Collapse Item1078            int     0x16
Expand/Collapse Item1079            testb   al, #0x08               ! Bit 3 = ALT key
Expand/Collapse Item1080            jz      noalt                   ! No ALT key pressed
int 0x16 is the keyboard BIOS function call.  If ah=2, int 0x16 tests the status of the control, shift and ALT keys.  If the third bit from the right (0x08 = 00000100) in the return value (al) is high, the ALT key has been pressed.

The "b" in movb and testb indicates that the instructions operate on bytes rather than words.

The difference between the test and the and instruction is that the test instruction doesn't change the destination operand (in this case al).  It only affects the flag register.  In this case we're concerned with the Z (zero) flag.  If al's third bit from the right isn't 1 (the alt key wasn't pressed), the testb instruction will set the Z flag and the jump is made in the next instruction.

noalt is on line 1098.

Expand/Collapse Item1081            call    print
Expand/Collapse Item1082            .data2  BUFFER+devhd
.data2 reserves 2 bytes for data.  Study print (line 1256) to see how this data is used.  Also look at memory location choice on line 1272

BUFFER+devhd is the string's beginning offset address in memory.

Expand/Collapse Item1083    getkey: xorb    ah, ah                  ! Wait for keypress
Expand/Collapse Item1084            int     0x16
Expand/Collapse Item1085            movb    BUFFER+choice, al
Expand/Collapse Item1086            subb    al, #0x30               ! al -= '0'
Expand/Collapse Item1087            cmpb    al, #10
Expand/Collapse Item1088            jl      keyok                   ! key in 0 - 9 range
Expand/Collapse Item1089            andb    al,#0x1f                ! ignore alpha case
Expand/Collapse Item1090            subb    al,#7                   ! correction for alpha keys
Expand/Collapse Item1091            cmpb    al,#20
Expand/Collapse Item1092            jae     getkey                  ! Key not in 0 - 19 range
At this point, the user has hit the ALT key and the code is waiting for the user to specify a partition (0-9, a-j).  When the user types in a value, the ascii value of the pressed key is placed in choice (line 1272), overwriting the initial '0'.  This ascii value is then converted to its corresponding integer value.  The ascii values for '0' through '9' are converted to the integers 0 through 9 and the ascii values for 'a' or 'A' through 'j' or 'J' are converted to the integers 10 through 19.  For a little help, here's an ascii chart.

 cmp is a subtraction that only affects the flag register.  In this way, cmp is similar to test.  The following jae jumps if the first operand in cmp is above or equal to the second operand.

Expand/Collapse Item1093    keyok:  push    ax
Since print uses ax, ax is pushed onto the stack; if ax isn't pushed (and then later popped (line 1096)), its value will be lost.  This is commonly done. For example, it's also done on line 1109.
1094           call    print                   ! Show the key typed
1095           .data2  BUFFER+choice
1096           pop     ax
1097           jmp     override
Expand/Collapse Item1098    noalt:
The ALT key wasn't pressed.  If fix is 0, a jump to findactive is made and the partition tables on the hard drives are searched for a non-zero bootind field.

A partition table entry with the non-zero bootind field indicates a bootable partition.

1099           movb    al, BUFFER+fix          ! Always boot a certain partition?
1100           testb   al, al
1101           jz      findactive              ! No, boot the active partition
Expand/Collapse Item1102    override:
A value between 0 and 19 is in al; this is the partition that will be booted.  Another master boot block from another device must be loaded if the partition isn't on the current device (remember that the current device is in dl).
1103           cbw                             ! ax = partition choice
1104           movb    dl, #5
Expand/Collapse Item1105           divb    dl                      ! al = disk, ah = partition within disk
For divb, ax is divided by dl (in this case) and the quotient is placed in al and the remainder in ah. al will have the value of the hard drive (0-3) and ah will have the value of the partition (0-4).
1106           movb    dl, #0x80
Expand/Collapse Item1107           addb    dl, al                  ! dl = disk
The BIOS uses the values 0x80, 0x81, 0x82, and 0x83 to indicate the 1st, 2nd, 3rd, and 4th hard drives.
1108           movb    al, ah                  ! al = partition within disk
Expand/Collapse Item1109           push    ax                      ! Save partition choice
The ax register is used by load0; since ax is needed on line 1113, its value is pushed and then popped (see line 1112).
Expand/Collapse Item1110           call    load0                   ! Get sector 0
load0  loads the first sector of the hard drive specified by dl.  Keep in mind that this master boot record may be the same as the master boot record that is currently executing.  We could have checked for this and saved the time it takes to load the master boot record but it would have added complexity to the code.

If the partition is 0, 5, 10, or 15, then the master boot record of the appropriate hard drive is loaded and executed (line 1114).  If the partition is not 0, 5, 10, or 15, the partition table from the master boot record that has just been loaded is sorted (line 1121) and the first sector from the desired partition is loaded (line 1146).  This sector either has another master boot record (in which case there are subpartitions on the partition that was chosen) or a bootstrap that will load the boot monitor from that partition.

1111           jb      error0                  ! Unable to read it
1112           pop     ax       &