/bootloader/stage1.asm
http://github.com/Pokelover980/Poke-and-Necro-Hobby-OS · Assembly · 243 lines · 199 code · 28 blank · 16 comment · 0 complexity · 8932d093f4233a442b387fbc1a649b54 MD5 · raw file
- ; -------------------------------------------------------------
- ; Pokelover and Necro's Hobby OS Bootloader - Stage 1
- ;
- ; Based on the MikeOS bootloader, which is based on the free
- ; bootloader by E Dehling. It looks for the STAGE2.BIN file on
- ; a FAT12 filesystem (specifically a floppy). Takes up exactly
- ; one sector and MUST end in 0xAA55, which is the bootloader
- ; signature.
- ; -------------------------------------------------------------
- [BITS 16] ; Let NASM know we want 16 bit mode, even though
- ; it should be able to detect it on it's own
- jmp short BootStart ; Jump over disk info.
- nop
- OEMLabel db "PNOSBOOT" ; Disk label
- BytesPerSector dw 512 ; Bytes per sector
- SectorsPerCluster db 1 ; Sectors per cluster
- ReservedForBoot dw 1 ; Reserved sectors for boot record
- NumberOfFats db 2 ; Number of copies of the FAT
- RootDirEntries dw 224 ; Number of entries in root dir
- ; (224 * 32 = 7168 = 14 sectors to read)
- LogicalSectors dw 2880 ; Number of logical sectors
- MediumByte db 0F0h ; Medium descriptor byte
- SectorsPerFat dw 9 ; Sectors per FAT
- SectorsPerTrack dw 18 ; Sectors per track (36/cylinder)
- Sides dw 2 ; Number of sides/heads
- HiddenSectors dd 0 ; Number of hidden sectors
- LargeSectors dd 0 ; Number of LBA sectors
- DriveNo dw 0 ; Drive No: 0
- Signature db 41 ; Drive signature: 41 for floppy
- VolumeID dd 00000000h ; Volume ID: any number
- VolumeLabel db "PNOS "; Volume Label: any 11 chars
- FileSystem db "FAT12 " ; File system type: don't change!
- BootStart:
- mov ax, 0x07C0 ; This is our entry point, we're going to set up
- ; a 4K stack space above this
- add ax, 544 ; And first we need a 544 paragraph buffer so we don't
- ; interfere with this or the disk buffer!
- cli ; Disable interrupts while changing stack
- mov ss, ax
- mov sp, 4096
- sti ; Restore interrupts
- mov ax, 0x07C0 ; Set data segment to where we've loaded to make things easier
- mov ds, ax
- mov byte [BootDev], dl ; Save boot device number
- mov eax, 0 ; Older BIOSes may need this
-
- FloppyOk: ; Ready to read first block of data
- mov ax, 19 ; Root dir starts at logical sector 19
- call l2hts
- mov si, Buffer ; Set ES:BX to our buffer
- mov bx, ds
- mov es, bx
- mov bx, si
- mov ah, 2 ; int 0x13 params: Read floppy sectors
- mov al, 14 ; 14 floppy sectors to read
- pusha ; Push registers to stack to prepare for loop
-
- ReadRootDir:
- popa ; Just in case int 0x13 modified anything
- pusha
- stc ; Not all BIOSes set properly on error
- int 0x13 ; Read sectors
- jnc SearchDir ; If read was OK, skip ahead
- call ResetFloppy ; If not, reset floppy and try again
- jnc ReadRootDir ; Did the floppy reset fine?
- jmp Reboot ; If it didn't, double error, restart
-
- SearchDir:
- popa
- mov ax, ds ; Root dir is now in [Buffer]
- mov es, ax ; Give this info to DI
- mov di, Buffer
- mov cx, word [RootDirEntries] ; Search all entries
- mov ax, 0 ; Start at 0
-
- NextRootEntry:
- xchg cx, dx ; We use cx in the inner loop
- mov si, BootFileName ; Start searching for stage2 filename
- mov cx, 11
- rep cmpsb
- je FoundFileToLoad ; Pointer DI will be at offset 11
- add ax, 32 ; Bump by one entry (32 bytes per entry)
- mov di, Buffer ; Point to next entry
- add di, ax
- xchg dx, cx ; Get cx back
- loop NextRootEntry
- mov si, NoFile
- call PrintString
- jmp Reboot
-
- FoundFileToLoad: ; Let's load the FAT into RAM
- mov ax, word[es:di+0x0F] ; Offset 11+15=26 contains our first cluster
- mov word[Cluster], ax
- mov ax, 1 ; Sector 1 = first sector of FAT
- call l2hts
- mov di, Buffer
- mov bx, di ; ES:BX points to our buffer
- mov ah, 2 ; int 0x13 params: read FAT sectors
- mov al, 9 ; All 9 sectors of first FAT
- pusha ; Push registers to stack to prepare for loop
-
- ReadFat:
- popa ; In case int 0x13 modified anything
- pusha
- stc
- int 0x13 ; Read sectors using BIOS
- jnc ReadFatOkay ; If read was okay, skip ahead
- call ResetFloppy ; Otherwise, reset floppy and try again
- jnc ReadFat ; Floppy reset OK?
- mov si, DiskError
- call PrintString ; If not, print an error and reboot
- jmp Reboot
- ReadFatOkay:
- popa
- mov ax, 0x2000 ; Segment where we're loading kernel
- mov es, ax
- mov bx, 0
- mov ah, 2 ; int 0x13 read params
- mov al, 1
- push ax ; Save in case it gets lost
-
- ; We're gonna load the FAT from the disk now
- LoadFileSector:
- mov ax, word [Cluster] ; Convert sector to logical
- add ax, 31
- call l2hts
- mov ax, 0x2000 ; Set buffer past what we've read
- mov es, ax
- mov bx, word [Pointer]
- pop ax ; Save in case it gets lost
- push ax
- stc
- int 0x13
- jnc CalculateNextCluster ; If there's no error
- call ResetFloppy ; If there is, reset floppy
- jmp LoadFileSector
-
- CalculateNextCluster:
- mov ax, [Cluster]
- mov dx, 0
- mov bx, 3
- mul bx
- mov bx, 2
- div bx ; DX = [Cluster] mod 2
- mov si, Buffer
- add si, ax ; AX = word in FAT for 12 bit entry
- mov ax, word [ds:si]
- or dx, dx ; If DX = 0 [Cluster] is even; if 1, [Cluster] is odd
- jz even ; If [Cluster] is even, drop last 4 bits of word with
- ; next clusters; if odd, drop first 4 bits
-
- odd:
- shr ax, 4
- jmp short NextClusterCont
-
- even:
- and ax, 0x0FFF ; Mask out final four bits
-
- NextClusterCont:
- mov word [Cluster], ax ; Store cluster
- cmp ax, 0x0FF8 ; 0xFF8 = end of file in FAT12
- jae end
- add word [Pointer], 512 ; Increase buffer point 1 sector
- jmp LoadFileSector
-
- end: ; Hooray, we've reached the end and got the file to load!
- pop ax ; Clean up stack, as we pushed AX earlier
- mov dl, byte[BootDev] ; Provide Stage2/Kernel with boot device info
- mov si, NoFile
- call PrintString
- jmp 0x2000:0x0 ; Jump to entry point of stage2!
-
- ; Subroutines below
- Reboot:
- mov ax, 0
- int 0x16 ; Wait for keystroke
- mov ax, 0
- int 0x19 ; Reboot
-
- PrintString:
- pusha
- mov ax, 0x0E
-
- .repeat:
- lodsb
- cmp al, 0
- je .done ; If char is 0, we've reached the end of the string
- int 0x10 ; Otherwise, we print it
- jmp short .repeat
-
- .done:
- popa
- ret
-
- ResetFloppy: ; Carry set on error
- push ax
- push dx
- mov ax, 0
- mov dl, byte [BootDev]
- stc
- int 0x13
- pop dx
- pop ax
- ret
-
- l2hts: ; Calculate head, track and sector for int 0x13
- push bx
- push ax
- mov bx, ax
- mov dx, 0
- div word [SectorsPerTrack]
- add dl, 0x01
- mov cl, dl
- mov ax, bx
- mov dx, 0
- div word [SectorsPerTrack]
- mov dx, 0
- div word [Sides]
- mov dh, dl
- mov ch, al
- pop ax
- pop bx
- mov dl, byte [BootDev]
- ret
-
-
- BootFileName db "STAGE2 BIN" ; Stage2 filename
- DiskError db "Disk error! Press any key to reboot...", 0 ; Something went wrong!
- NoFile db "No STAGE2.BIN", 0 ; Someone forgot to add something...
- BootDev db 0
- Cluster dw 0
- Pointer dw 0
- times 510-($-$$) db 0
- dw 0AA55h
- Buffer: