root/boot.s

/* [<][>][^][v][top][bottom][index][help] */
#===============================================================================
# This Boot Sector borrows heavily from "Write Your Own 32-bit Operating System
#===============================================================================
        .include "macros.s"
        .include "memory.inc"

        .code16
        .org    0
        .global _start

_start:
        jmp Bootup
        nop

Herald:         .ascii "MYOSVER1"
nBytesPerSect:  .word 0x0200
nSectPerClstr:  .byte 0x01
nRsvdSect:      .word 0x0001
nFATS:          .byte 0x02
nRootDirEnts:   .word 0x00E0
nTotalSectors:  .word 0x0B40
bMedia:         .byte 0xF0
nSectPerFAT:    .word 0x0009
nSectPerTrack:  .word 0x0012
nHeads:         .word 0x0002
nHidden:        .long 0x00000000
nTotalSect32:   .long 0x00000000
bBootDrive:     .byte 0x00
ResvdByte:      .byte 0x00
ExtBootSig:     .byte 0x29
nOSSectors:     .word 0x0080
ResvsWord:      .word 0x3F51
Volname:        .ascii "RICH       "
FatType:        .ascii "FAT12   "

# Relocate boot sector to 0x90000
Bootup:
        cli
        mov $0x9000, %ax
        mov %ax, %ss
        mov $0x8000, %sp
        mov $0x9000, %ax
        mov %ax, %es
        xor %di, %di
        mov $0x7C0, %ax
        mov %ax, %ds
        xor %si, %si
        mov $512, %cx
        rep movsb

# The next 5 instructions effect a long jump to 0x9000:here
        mov $0x9000, %ax
        push %ax
        mov $here, %ax #6fh
        push %ax
        lret

# The following code calculates the start sector of the first data file and put it in register ax
# This will work out as 0x21, which could have been hard-coded. Doing the calculation makes it
# easier to extend this floppy boot sector to a hard-disk boot sector.
here:
        push %es
        pop %ds
        mov nSectPerTrack, %cx
        xor %ax, %ax
        mov %ax, %ds
        mov $0x0078, %bx
        lds (%bx), %si
        mov %cl, 4(%si)
        movb $0x0f, 9(%si)
        push %es
        pop %ds
        push %ds
        sti
        mov (bBootDrive), %dl
        xor %ax, %ax
        int $0x13
        jc BadBoot
        pop %ds
        mov $MsgLoad, %si
        call PutChars
        xor %ax, %ax
        mov (nFATS), %al
        mulw (nSectPerFAT)
        add (nHidden), %ax
        adc (nHidden+2), %dx
        add (nRsvdSect), %ax
        mov %ax, %cx
        mov $0x20, %ax
        mulw (nRootDirEnts)
        mov (nBytesPerSect), %bx
        div %bx
        add %cx, %ax
        mov (nOSSectors), %cx
        jmp ContinueBoot

BadBoot:
        mov $MsgBadDisk, %si
        call PutChars
        xor %ax, %ax
        int $16
        int $19

PutChars:
        lodsb
        or %al, %al
        jz Done
        mov $0xe, %ah
        mov $0x7, %bx
        int $0x10
        jmp PutChars
Done:
        ret

# Load the 0x80 sectors of OS code to 0x1000
ContinueBoot:
        mov $0x100, %bx
        mov %bx, %es
NextSector:
        push %ax
        push %cx
        push %dx
        push %es
        xor %bx, %bx
        mov (nSectPerTrack), %si
        div %si
        inc %dl
        mov %dl, (ResvdByte)
        xor %dx, %dx
        divw (nHeads)
        mov (bBootDrive), %dh
        xchg %dl, %dh
        mov %ax, %cx
        xchg %cl, %ch
        shl $6, %cl
        or (ResvdByte), %cl
        mov $1, %al
        mov $2, %ah
        int $0x13
        jc  BadBoot
        mov $MsgDot, %si
        call PutChars           # Print a "." for each sector loaded
        pop %es
        pop %dx
        pop %cx
        pop %ax
        mov %es, %bx
        add $0x20, %bx
        mov %bx, %es
        inc %ax
        loop NextSector
        mov $0x9000, %ax
        mov %ax, %ds

# relocate GDT
        mov $GDT, %ax
        mov %ax, %es
        mov $0, %di
        lea (mygdt), %si
        mov $0x40, %cx
        cld
        rep movsb

#enable_a20:
        xor %cx, %cx
IBEmm0:
        cli
        in  $0x64, %al
        test $2, %al
        jnz IBEmm0
        mov $0xD1, %al
        out %al, $0x64
        xor %cx, %cx

IBEmm1:
        cli
        in  $0x64, %al
        test $2, %al
        jnz IBEmm1
        mov $0xDF, %al
        out %al, $0x60
        xor %cx, %cx

# load register gdt and enable Protected Mode
        lgdt (gdt_48)
        mov %cr0, %eax
        bts $0x0, %eax
        mov %eax, %cr0

# jump to the start of the OS code (startup.s)
        jmp $0x8, $0x1000

#===================================================
# Global Descriptor Table - will be relocated to 0x0
#===================================================
mygdt:  .quad   0x0                                             # null descriptor - first entry in GDT must be null
        CODE_SEG_DESCR OsCodeSeg,0x0,0xfffff,0  # 32-bit descriptors
        DATA_SEG_DESCR OsDataSeg,0x0,0xfffff
        CODE64_SEG_DESCR code64, 0                              # 64-bit descriptors
        DATA64_SEG_DESCR data64, 0
        DATA64_SEG_DESCR udata64, 3
        CODE64_SEG_DESCR user64, 3

GDTlength = . - mygdt

gdt_48:         .word   0x800     # allow up to 512 entries in GDT
                .double 0x00000000

MsgBadDisk:     .byte 0x0D,0x0A
                .ascii "Bad Boot Disk!"
                .byte 0x00
MsgLoad:        .byte 0x0D,0x0A
                .ascii "Loading IanOS"
                .byte 0x00
MsgDot:         .byte '.',0

#====================================================================================
# Ensure that the bootsector is 512 bytes and add a boot signature at the end of it
#====================================================================================

                .org  510
BootSig:        .word 0xAA5F

/* [<][>][^][v][top][bottom][index][help] */