org 0 ;Expect code to be located at adress 0 ;====================================================; ; Compile time Constants ; ;====================================================; drive_id equ BOOT_ENTRY ;- BYTE --------------; segment_to_fat equ ENTRY ;- WORD --------------; ptr_to_fat equ ENTRY + 2 ;- WORD --------------; ptr_to_root equ ENTRY + 4 ;- WORD --------------; ;====================================================; ; CODE ENTRY ; ;====================================================; BOOT_ENTRY: ;====================================================; ; 1.44MB FLOPPY BPB ; ;====================================================; ;-- far jump in order to instantly find the right start pointer --; jmp 07c0h:ENTRY ; OEM_NAME: db "-MAXIX" ;first two bytes of OEM name used by "jmp" instruction BYTES_PER_SECTOR: dw 0x200 SECTORS_PER_CLUSTER: db 16 RESERVED_CLUSTERS: dw 1 NUMBER_OF_FATS: db 2 ROOT_DIRECTORY_ENTRIES: dw 224 TOTAL_SECTORS: dw 2880 MEDIA_DESCRIPTOR: db 0xf0 SECTORS_PER_FAT: dw 9 SECTORS_PER_TRACK: dw 12 HEADS: dw 2 HIDDEN_SECTORS: dw 0 ENTRY: ;----------------------------------------; ;SETUP ; ;----------------------------------------; cld ; forward direction mov BYTE[drive_id], dl ; preserve drive ID ;-- Give CS and DS same value ----; push cs ; pop ds ; ;-- Setup stack ------------------; cli ; mitigate possible problems with interrupts push cs ; pop ss ; SS:Code-segment mov sp, 0h ; SP:2,5Kb- above code sti ; enable interrupts ;-- print notice -----------------; mov si, READING_FAT_MESSAGE ; call DISPLAY ; ;-- read fat and root sector -----; call GET_FAT_SECTOR ; mov ax, dx ; ;-- get CHS of FAT sector --------; call LBA_TO_CSH ; ;-- setup reading of the disk ----; ;push 3 ; amount of tries before giving up mov ah, 2 ; int 13, 2 mov al, BYTE[SECTORS_PER_FAT] ; amount of sectors to read add al, BYTE[SECTORS_PER_CLUSTER] ; also read the ROOT sector mov bx, 0x0A00 ; buffer mov dl, BYTE[drive_id] ; drive id we preserved earlier @@RETRY_FAT: ; ;push cx ; preserve cx int 13 ; ;pop cx ; get amount of tries left ;loopne @@RETRY_FAT ; retry if error ;-- done reading FAT -------------; mov si, MSG_DONE ; call DISPLAY ; ;-- setting up constants ---------; mov ptr_to_fat, 0xA00 ; ;========================================= ;----------------------------------------; ; FIND_KERNEL_IN_ROOT ; ; finds the kernel in the root sector ; ;----------------------------------------; FIND_KERNEL_IN_ROOT: xor di, di ;-- ;========================================= ;----------------------------------------; ; REBOOT ; ; re-enter the BSS ; ;----------------------------------------; REBOOT: ;-- wait for key input --; xor ax, ax ; int 16h ; ;-- re-enter BSS --------; int 19h ; ;-- bootloader is done --; ;========================================= ;---------------------------------------; ; GET_FATS_SIZE ; ; calculates the size of the FATS ; ;---------------------------------------; ; output: ax -> size of the FATS ; ;---------------------------------------; GET_FATS_SIZE: mov ax, WORD[SECTORS_PER_FAT] mul BYTE[NUMBER_OF_FATS] ret ;======================================== ;---------------------------------------; ; GET_FAT_SECTOR ; ; calculates the start of the FAT ; ;---------------------------------------; ; output: dx -> sector of the fat ; ;---------------------------------------; GET_FAT_SECTOR: ;-- initialize variables -----------; xor dx, dx ; xor ax, ax ; mov al, BYTE[SECTORS_PER_CLUSTER] ; AX = Sectors per cluster mov bx, WORD[RESERVED_CLUSTERS] ; BX = reserved clusters mov cx, WORD[HIDDEN_SECTORS] ; CX = hidden sectors push ax ; ;-- reserved clusters --------------; mul bx ; ax = reserved * sec_per_cl mov dx, ax ; dx = bx ;-- hidden sectors -----------------; pop ax ; mul cx ; ax = hidden * sec_per_cl ;-- prepare result -----------------; add dx, ax ; inc dx ; ret ; ;========================================= ;----------------------------------------; ; LBA_TO_CSH ; ; converts LBA to cylinder, sector, ; ; head ; ;----------------------------------------; ; input: ax -> LBA ; ; output: ch -> cylinder ; ; : cl -> sector ; ; : dh -> head ; ;----------------------------------------; LBA_TO_CSH: xor dx, dx ;-- calculate the sector ---------; div WORD[SECTORS_PER_TRACK] ; ax = int(lba / sectors_per_track) inc dx ; dx = sector mov bx, dx ; db = dx xor dx, dx ; ;-- calculate head & cylinder ----; div WORD[HEADS] ; ax = sector mov cx, dx ; cx = head ;-- move to correct register -----; mov cl, bl ; cl = sector mov dh, cl ; dh = head or ch, al ; ch = sector ret ; ;========================================= ;----------------------------------------; ; DISPLAY ; ; displays a string ; ;----------------------------------------; ;input: string pointer in si ; ;----------------------------------------; DISPLAY: lodsb ; AL=DS:[SI], increments SI by 1 ;-- Setup syscall ----; mov ah, 0eh ; mov bx, 7 ; int 10h ; call the system call with ;-- is string done? --; or al,al ; jnz DISPLAY ; if not so, go back to display ret ;======================================== ;----------------------------------------; ; TEXT CONSTANTS ; ;----------------------------------------; READING_FAT_MESSAGE: db "READING FAT", 10, 13, 0 READING_ROOTS_MESSAGE: db "READING ROOT SECTOR", 10, 13, 0 MSG_DONE: db "DONE", 10, 13, 0 MSG_BPOINT: db "BREAKPOINT", 10, 13, 0 KERNEL_FILENAME: db 'kernel bin' ;========================================= times 510 - ($ - $$) db 0 dw 55aah db 0Fh dw 0FFFFh