The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/boot/bootblock.s

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 !       Bootblock 1.5 - Minix boot block.               Author: Kees J. Bot
    2 !                                                               21 Dec 1991
    3 !
    4 ! When the PC is powered on, it will try to read the first sector of floppy
    5 ! disk 0 at address 0x7C00.  If this fails due to the absence of flexible
    6 ! magnetic media, it will read the master boot record from the first sector
    7 ! of the hard disk.  This sector not only contains executable code, but also
    8 ! the partition table of the hard disk.  When executed, it will select the
    9 ! active partition and load the first sector of that at address 0x7C00.
   10 ! This file contains the code that is eventually read from either the floppy
   11 ! disk, or the hard disk partition.  It is just smart enough to load /boot
   12 ! from the boot device into memory at address 0x10000 and execute that.  The
   13 ! disk addresses for /boot are patched into this code by installboot as 24-bit
   14 ! sector numbers and 8-bit sector counts above enddata upwards.  /boot is in
   15 ! turn smart enough to load the different parts of the Minix kernel into
   16 ! memory and execute them to finally get Minix started.
   17 !
   18 
   19         LOADOFF    =    0x7C00  ! 0x0000:LOADOFF is where this code is loaded
   20         BOOTSEG    =    0x1000  ! Secondary boot code segment.
   21         BOOTOFF    =    0x0030  ! Offset into /boot above header
   22         BUFFER     =    0x0600  ! First free memory
   23         LOWSEC     =         8  ! Offset of logical first sector in partition
   24                                 ! table
   25 
   26         ! Variables addressed using bp register
   27         device     =         0  ! The boot device
   28         lowsec     =         2  ! Offset of boot partition within drive
   29         secpcyl    =         6  ! Sectors per cylinder = heads * sectors
   30 
   31 .text
   32 
   33 ! Start boot procedure.
   34 
   35 boot:
   36         xor     ax, ax          ! ax = 0x0000, the vector segment
   37         mov     ds, ax
   38         cli                     ! Ignore interrupts while setting stack
   39         mov     ss, ax          ! ss = ds = vector segment
   40         mov     sp, #LOADOFF    ! Usual place for a bootstrap stack
   41         sti
   42 
   43         push    ax
   44         push    ax              ! Push a zero lowsec(bp)
   45 
   46         push    dx              ! Boot device in dl will be device(bp)
   47         mov     bp, sp          ! Using var(bp) is one byte cheaper then var.
   48 
   49         push    es
   50         push    si              ! es:si = partition table entry if hard disk
   51 
   52         mov     di, #LOADOFF+sectors    ! char *di = sectors;
   53 
   54         testb   dl, dl          ! Winchester disks if dl >= 0x80
   55         jge     floppy
   56 
   57 winchester:
   58 
   59 ! Get the offset of the first sector of the boot partition from the partition
   60 ! table.  The table is found at es:si, the lowsec parameter at offset LOWSEC.
   61 
   62         eseg
   63         les     ax, LOWSEC(si)    ! es:ax = LOWSEC+2(si):LOWSEC(si)
   64         mov     lowsec+0(bp), ax  ! Low 16 bits of partition's first sector
   65         mov     lowsec+2(bp), es  ! High 16 bits of partition's first sector
   66 
   67 ! Get the drive parameters, the number of sectors is bluntly written into the
   68 ! floppy disk sectors/track array.
   69 
   70         movb    ah, #0x08       ! Code for drive parameters
   71         int     0x13            ! dl still contains drive
   72         andb    cl, #0x3F       ! cl = max sector number (1-origin)
   73         movb    (di), cl        ! Number of sectors per track
   74         incb    dh              ! dh = 1 + max head number (0-origin)
   75         jmp     loadboot
   76 
   77 ! Floppy:
   78 ! Execute three read tests to determine the drive type.  Test for each floppy
   79 ! type by reading the last sector on the first track.  If it fails, try a type
   80 ! that has less sectors.  Therefore we start with 1.44M (18 sectors) then 1.2M
   81 ! (15 sectors) ending with 720K/360K (both 9 sectors).
   82 
   83 next:   inc     di              ! Next number of sectors per track
   84 
   85 floppy: xorb    ah, ah          ! Reset drive
   86         int     0x13
   87 
   88         movb    cl, (di)        ! cl = number of last sector on track
   89 
   90         cmpb    cl, #9          ! No need to do the last 720K/360K test
   91         je      success
   92 
   93 ! Try to read the last sector on track 0
   94 
   95         mov     es, lowsec(bp)  ! es = vector segment (lowsec = 0)
   96         mov     bx, #BUFFER     ! es:bx buffer = 0x0000:0x0600
   97         mov     ax, #0x0201     ! Read sector, #sectors = 1
   98         xorb    ch, ch          ! Track 0, last sector
   99         xorb    dh, dh          ! Drive dl, head 0
  100         int     0x13
  101         jc      next            ! Error, try the next floppy type
  102 
  103 success:movb    dh, #2          ! Load number of heads for multiply
  104 
  105 loadboot:
  106 ! Load /boot from the boot device
  107 
  108         movb    al, (di)        ! al = (di) = sectors per track
  109         mulb    dh              ! dh = heads, ax = heads * sectors
  110         mov     secpcyl(bp), ax ! Sectors per cylinder = heads * sectors
  111 
  112         mov     ax, #BOOTSEG    ! Segment to load /boot into
  113         mov     es, ax
  114         xor     bx, bx          ! Load first sector at es:bx = BOOTSEG:0x0000
  115         mov     si, #LOADOFF+addresses  ! Start of the boot code addresses
  116 load:
  117         mov     ax, 1(si)       ! Get next sector number: low 16 bits
  118         movb    dl, 3(si)       ! Bits 16-23 for your up to 8GB partition
  119         xorb    dh, dh          ! dx:ax = sector within partition
  120         add     ax, lowsec+0(bp)
  121         adc     dx, lowsec+2(bp)! dx:ax = sector within drive
  122         cmp     dx, #[1024*255*63-255]>>16  ! Near 8G limit?
  123         jae     bigdisk
  124         div     secpcyl(bp)     ! ax = cylinder, dx = sector within cylinder
  125         xchg    ax, dx          ! ax = sector within cylinder, dx = cylinder
  126         movb    ch, dl          ! ch = low 8 bits of cylinder
  127         divb    (di)            ! al = head, ah = sector (0-origin)
  128         xorb    dl, dl          ! About to shift bits 8-9 of cylinder into dl
  129         shr     dx, #1
  130         shr     dx, #1          ! dl[6..7] = high cylinder
  131         orb     dl, ah          ! dl[0..5] = sector (0-origin)
  132         movb    cl, dl          ! cl[0..5] = sector, cl[6..7] = high cyl
  133         incb    cl              ! cl[0..5] = sector (1-origin)
  134         movb    dh, al          ! dh = al = head
  135         movb    dl, device(bp)  ! dl = device to read
  136         movb    al, (di)        ! Sectors per track - Sector number (0-origin)
  137         subb    al, ah          ! = Sectors left on this track
  138         cmpb    al, (si)        ! Compare with # sectors to read
  139         jbe     read            ! Can't read past the end of a cylinder?
  140         movb    al, (si)        ! (si) < sectors left on this track
  141 read:   push    ax              ! Save al = sectors to read
  142         movb    ah, #0x02       ! Code for disk read (all registers in use now!)
  143         int     0x13            ! Call the BIOS for a read
  144         pop     cx              ! Restore al in cl
  145         jmp     rdeval
  146 bigdisk:
  147         movb    cl, (si)        ! Number of sectors to read
  148         push    si              ! Save si
  149         mov     si, #LOADOFF+ext_rw ! si = extended read/write parameter packet
  150         movb    2(si), cl       ! Fill in # blocks to transfer
  151         mov     4(si), bx       ! Buffer address
  152         mov     8(si), ax       ! Starting block number = dx:ax
  153         mov     10(si), dx
  154         movb    dl, device(bp)  ! dl = device to read
  155         movb    ah, #0x42       ! Extended read
  156         int     0x13
  157         pop     si              ! Restore si to point to the addresses array
  158         !jmp    rdeval
  159 rdeval:
  160         jc      error           ! Jump on disk read error
  161         movb    al, cl          ! Restore al = sectors read
  162         addb    bh, al          ! bx += 2 * al * 256 (add bytes read)
  163         addb    bh, al          ! es:bx = where next sector must be read
  164         add     1(si), ax       ! Update address by sectors read
  165         adcb    3(si), ah       ! Don't forget bits 16-23 (add ah = 0)
  166         subb    (si), al        ! Decrement sector count by sectors read
  167         jnz     load            ! Not all sectors have been read
  168         add     si, #4          ! Next (address, count) pair
  169         cmpb    ah, (si)        ! Done when no sectors to read
  170         jnz     load            ! Read next chunk of /boot
  171 
  172 done:
  173 
  174 ! Call /boot, assuming a long a.out header (48 bytes).  The a.out header is
  175 ! usually short (32 bytes), but to be sure /boot has two entry points:
  176 ! One at offset 0 for the long, and one at offset 16 for the short header.
  177 ! Parameters passed in registers are:
  178 !
  179 !       dl      = Boot-device.
  180 !       es:si   = Partition table entry if hard disk.
  181 !
  182         pop     si              ! Restore es:si = partition table entry
  183         pop     es              ! dl is still loaded
  184         jmpf    BOOTOFF, BOOTSEG  ! jmp to sec. boot (skipping header).
  185 
  186 ! Read error: print message, hang forever
  187 error:
  188         mov     si, #LOADOFF+errno+1
  189 prnum:  movb    al, ah          ! Error number in ah
  190         andb    al, #0x0F       ! Low 4 bits
  191         cmpb    al, #10         ! A-F?
  192         jb      digit           ! 0-9!
  193         addb    al, #7          ! 'A' - ':'
  194 digit:  addb    (si), al        ! Modify '0' in string
  195         dec     si
  196         movb    cl, #4          ! Next 4 bits
  197         shrb    ah, cl
  198         jnz     prnum           ! Again if digit > 0
  199 
  200         mov     si, #LOADOFF+rderr  ! String to print
  201 print:  lodsb                   ! al = *si++ is char to be printed
  202         testb   al, al          ! Null byte marks end
  203 hang:   jz      hang            ! Hang forever waiting for CTRL-ALT-DEL
  204         movb    ah, #0x0E       ! Print character in teletype mode
  205         mov     bx, #0x0001     ! Page 0, foreground color
  206         int     0x10            ! Call BIOS VIDEO_IO
  207         jmp     print
  208 
  209 .data
  210 rderr:  .ascii  "Read error "
  211 errno:  .ascii  "00 \0"
  212 errend:
  213 
  214 ! Floppy disk sectors per track for the 1.44M, 1.2M and 360K/720K types:
  215 sectors:
  216         .data1  18, 15, 9
  217 
  218 ! Extended read/write commands require a parameter packet.
  219 ext_rw:
  220         .data1  0x10            ! Length of extended r/w packet
  221         .data1  0               ! Reserved
  222         .data2  0               ! Blocks to transfer (to be filled in)
  223         .data2  0               ! Buffer address offset (tbfi)
  224         .data2  BOOTSEG         ! Buffer address segment
  225         .data4  0               ! Starting block number low 32 bits (tbfi)
  226         .data4  0               ! Starting block number high 32 bits
  227 
  228         .align  2
  229 addresses:
  230 ! The space below this is for disk addresses for a 38K /boot program (worst
  231 ! case, i.e. file is completely fragmented).  It should be enough.

Cache object: 979a13d47bd59564310d4ce03d4e2e95


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.