;********************************************************* ; RootOS - Bootloader / A20 ; Author: Simon Wollwage a.k.a. rootnode ;********************************************************* %ifndef __A20_INCLUDED_ %define __A20_INCLUDED_ bits 16 global _enable_a20 _enable_a20: pusha cli mov cx, 5 .enable_a20_start: .kbrd_cntrl_wait: xor ax, ax in al, 64h bt ax, 1 jc .kbrd_cntrl_wait mov al, 0dfh out 64h, al .kbrd_cntrl_wait_2: xor ax, ax in al, 64h bt ax, 1 jc .kbrd_cntrl_wait_2 .kbrd_cntrl_get_state: xor ax, ax in al, 60h bt ax, 1 jc .enable_a20_success loop .enable_a20_start jmp .enable_a20_fail .enable_a20_success: popa xor eax, eax ret .enable_a20_fail: popa mov eax, -1 ret %endif ;********************************************************* ; RootOS - Bootloader / Global Descriptor Table ; Author: Simon Wollwage a.k.a. rootnode ;********************************************************* %ifndef __GDT_INC_F458AD93BB62943A_INCLUDED_ %define __GDT_INC_F458AD93BB62943A_INCLUDED_ bits 16 install_gdt: cli pusha lgdt [toc] sti popa ret gdt_data: dd 0 ; null descriptor dd 0 ; gdt code: dw 0FFFFh ; limit low dw 0 ; base low db 0 ; base middle db 10011010b ; access db 11001111b ; granularity db 0 ; base high ; gdt data: ; data descriptor dw 0FFFFh ; limit low (Same as code)10:56 AM 7/8/2007 dw 0 ; base low db 0 ; base middle db 10010010b ; access db 11001111b ; granularity db 0 ; base high end_of_gdt: toc: dw end_of_gdt - gdt_data - 1 ; limit (Size of GDT) dd gdt_data ; base of GDT %endif ;********************************************************* ; RootOS - Bootloader / Input-/Output routines ; Author: Simon Wollwage a.k.a. rootnode ;********************************************************* %ifndef __STDIO_INC_F458AD93BB62943A_INCLUDED_ %define __STDIO_INC_F458AD93BB62943A_INCLUDED_ ;********************************************************* ; Output routines for 16 bit unprotected mode bits 16 puts16: pusha .loop_16: lodsb or al, al jz puts16_done mov ah, 0eh int 10h jmp .loop_16 puts16_done: popa ret ;********************************************************* ; Output routines for 32 bit PMode bits 32 %define VIDMEM 0xB8000 %define COLS 80 %define LINES 25 ;%define CHAR_ATTRIB 31 ; blue/white %define CHAR_ATTRIB 10 _cur_x db 0 _cur_y db 0 putch32: pusha mov edi, VIDMEM ;********************************************************* ; Retrieve position xor eax, eax mov ecx, COLS * 2 mov al, byte [_cur_y] mul ecx push eax mov al, byte [_cur_x] mov cl, 2 mul cl pop ecx add eax, ecx xor ecx, ecx add edi, eax ;********************************************************* ; Search for newline cmp bl, 0x0A je .row mov dl, bl mov dh, CHAR_ATTRIB mov word [edi], dx inc byte [_cur_x] ;cmp byte [_cur_x], COLS ;je .row jmp .done .row: mov byte [_cur_x], 0 inc byte [_cur_y] .done: popa ret bits 32 puts32: pusha push ebx pop edi .loop: mov bl, byte [edi] cmp bl, 0 je .done call putch32 .next: inc edi jmp .loop .done: mov bh, byte [_cur_y] mov bl, byte [_cur_x] call mov_cur popa ret mov_cur: pusha xor eax, eax mov ecx, COLS mov al, bh mul ecx add al, bl mov ebx, eax mov al, 0x0F mov dx, 0x03D4 out dx, al mov al, bl mov dx, 0x03D5 out dx, al xor eax, eax mov al, 0x0E mov dx, 0x03D4 out dx, al mov al, bh mov dx, 0x03D5 out dx, al popa ret bits 32 space db ' ', 0x0A, 0 clrscr32: pusha mov byte [_cur_x], 0 mov byte [_cur_y], 0 mov ecx, LINES .loop: lea ebx, [space] call puts32 loopz .loop mov byte [_cur_x], 0 mov byte [_cur_y], 0 popa ret %endif ;********************************************************* ; RootOS - Bootloader / Stage 1 ; Author: Simon Wollwage a.k.a. rootnode ;********************************************************* ;********************************************************* ; Since we are running on x86, we have to start in ; 16 bit mode bits 16 ;********************************************************* ; Set the origin to the beginning of the bootloader memory section ; Beginning of sector 1 org 0 ;********************************************************* ; Jump over the definitions directly to the loader start: jmp main ;********************************************************* ; fill up to have 512 bytes in size ; TIMES 0Bh - $ + Start db 0 ;********************************************************* bpbOEM db "RootOS " ; This member must be exactly 8 bytes ;********************************************************* ; some constants for a FAT File System bpbBytesPerSector: dw 512 bpbSectorsPerCluster: db 1 bpbReservedSectors: dw 1 bpbNumberOfFATs: db 2 bpbRootEntries: dw 224 bpbTotalSectors: dw 2880 bpbMeda: db 0xF0 bpbSectorsPerFAT: dw 9 bpbSectorsPerTrack: dw 18 bpbHeadsPerCylinder: dw 2 bpbHiddenSectors: dd 0 bpbTotalSectorsBig: dd 0 bsDriveNumber: db 0 bsUnused: db 0 bsExtBootSignature: db 0x29 bsSerialNumber: dd 0xA0A1A2A3 bsVolumeLabel: db "MOS FLOPPY " bsFileSystem: db "FAT12 " print: lodsb or al, al jz printdone mov ah, 0eh int 10h jmp print printdone: ret absoluteSector db 0x00 absoluteHead db 0x00 absoluteTrack db 0x00 ;********************************************************* ; Converts CHS to LBA Cluster2LBA: sub ax, 0x0002 xor cx, cx mov cl, BYTE [bpbSectorsPerCluster] mul cx add ax, WORD [dataSector] ret ;********************************************************* ; Converts LBA to CHS lba2chs: xor dx, dx div WORD [bpbSectorsPerTrack] inc dl mov BYTE [absoluteSector], dl xor dx, dx div WORD [bpbHeadsPerCylinder] mov BYTE [absoluteHead], dl mov BYTE [absoluteTrack], al ret ;********************************************************* ; Read sectors readsectors: .main mov di, 0x0005 ; Allow at most five error retries .sectorloop push ax push bx push cx call lba2chs ; convert first sector to LBA format mov ah, 0x02 ; BIOS read sector mov al, 0x01 ; read sector mov ch, BYTE [absoluteTrack] ; get track mov cl, BYTE [absoluteSector] ; get sector mov dh, BYTE [absoluteHead] ; get head mov dl, BYTE [bsDriveNumber] ; get drive int 0x13 ; call bios jnc .success ; test for errors xor ax, ax ; reset the disk int 0x13 ; call bios dec di ; dec error count pop cx ; restore registers pop bx ; " pop ax ; " jnz .sectorloop ; read again int 0x18 .success mov si, sProgress call print pop cx pop bx pop ax add bx, WORD [bpbBytesPerSector] inc ax loop .main ret ;********************************************************* ; Bootloader Entry point main: cli ; turn off interrupts mov ax, 0x07C0 mov ds, ax mov es, ax mov fs, ax mov gs, ax ;********************************************************* ; Create the stack mov ax, 0x0000 mov ss, ax mov sp, 0xFFFF sti ; turn on interrupts ;********************************************************* ; Display loading screen mov si, sLoadingMessage call print ;********************************************************* ; Load root directory descritpr table load_root: xor cx, cx xor dx, dx mov ax, 0x0020 mul WORD [bpbRootEntries] div WORD [bpbBytesPerSector] xchg ax, cx mov al, BYTE [bpbNumberOfFATs] mul WORD [bpbSectorsPerFAT] add ax, WORD [bpbReservedSectors] mov WORD [dataSector], ax add WORD [dataSector], cx mov bx, 0x0200 call readsectors ;********************************************************* ; Find stage 2 loader mov cx, WORD [bpbRootEntries] mov di, 0x0200 .loop: push cx mov cx, 0x000B mov si, ImageName push di rep cmpsb pop di je load_fat pop cx add di, 0x0020 loop .loop jmp failure load_fat: mov si, sCLRF call print mov dx, WORD [di + 0x001A] mov WORD [cluster], dx xor ax, ax mov al, BYTE [bpbNumberOfFATs] mul WORD [bpbSectorsPerFAT] mov cx, ax mov ax, WORD [bpbReservedSectors] mov bx, 0x0200 call readsectors mov si, sCLRF call print mov ax, 0x0050 mov es, ax mov bx, 0x0000 push bx ;********************************************************* ; Load stage 2 load_image: mov ax, WORD [cluster] pop bx call Cluster2LBA xor cx, cx mov cl, BYTE [bpbSectorsPerCluster] call readsectors push bx ;********************************************************* ; Process to next cluster mov ax, WORD [cluster] mov cx, ax mov dx, ax shr dx, 0x0001 add cx, dx mov bx, 0x0200 add bx, cx mov dx, WORD [bx] test ax, 0x0001 jnz .odd_cluster .even_cluster: and dx, 0000111111111111b jmp .done .odd_cluster: shr dx, 0x0004 .done: mov WORD [cluster], dx cmp dx, 0x0FF0 jb load_image done: mov si, sCLRF call print push WORD 0x0050 push WORD 0x0000 retf failure: mov si, sFailure call print mov ah, 0x00 int 0x16 int 0x19 dataSector dw 0x0000 cluster dw 0x0000 ImageName db "STAGE2 SYS" sLoadingMessage db 0x0D, 0x0A, "Loading boot image ", 0x0D, 0x0A, 0x00 sCLRF db 0x0D, 0x0A, 0x00 sProgress db "*", 0x00 sFailure db 0x0D, 0x0A, "ERROR: Please press any key to reboot", 0x00 ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ; fill up the rest of the 512 byte times 510 - ($-$$) db 0 ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ; This signature is needed! ; Without it, the BIOS won't recognize us as a bootloader dw 0xAA55