Unreal mode loading procedure
Posted: Tue Oct 25, 2011 1:05 pm
How do I use fat12 to point to an unreal mode data location? I am using the information found in the Unreal Mode section of the wiki, and have that booting, but I want to use fat12 to find a kernel file, and jump to it at 1MB. Is this possible?
Here is my current code. Trying to modify a real mode fat12 loader to work. I am sure I am doing it improperly, however. Any help would be appreciated.
Code: Select all
[BITS 16]
[ORG 0x7C00]
jmp boot
nop
OEMLabel db "HARMONY" ; 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
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 "HARMONY OS "; Volume Label: any 11 chars
FileSystem db "FAT12 " ; File system type: don't change!
wait_kbdbuf:
in al, 0x64
test al, 0x02
loopnz wait_kbdbuf
ret
enable_a20:
xor cx, cx
call wait_kbdbuf
mov al, 0xD1
out 0x64, al
call wait_kbdbuf
mov al, 0xDF
out 0x60, al
call wait_kbdbuf
push ds
push es
xor ax, ax
mov ds, ax
dec ax,
mov es, ax
mov ax,[es:0x10]
not ax
push WORD [0]
mov [0], ax
mov ax,[0]
cmp ax,[es:0x10]
pop WORD [0]
pop es
pop ds
jz .enable_a20_failed
ret
.enable_a20_failed:
jmp reboot
go_unreal:
push ds
lgdt [gdtr]
mov eax, cr0
or al,0x01
mov cr0, eax
mov bx, 0x08
mov ds, bx
and al, 0xFE
mov cr0, eax
pop ds
ret
; ------------------------------------------------------------------
; BOOTLOADER SUBROUTINES
reboot:
mov ax, 0
int 19h ; Reboot the system
reset_floppy: ; IN: [bootdev] = boot device; OUT: carry set on error
push ax
push dx
mov ax, 0
mov dl, byte [bootdev]
stc
int 13h
pop dx
pop ax
ret
l2hts: ; Calculate head, track and sector settings for int 13h
; IN: logical sector in AX, OUT: correct registers for int 13h
push bx
push ax
mov bx, ax ; Save logical sector
mov dx, 0 ; First the sector
div word [SectorsPerTrack]
add dl, 01h ; Physical sectors start at 1
mov cl, dl ; Sectors belong in CL for int 13h
mov ax, bx
mov dx, 0 ; Now calculate the head
div word [SectorsPerTrack]
mov dx, 0
div word [Sides]
mov dh, dl ; Head/side
mov ch, al ; Track
pop ax
pop bx
mov dl, byte [bootdev] ; Set correct device
ret
; ------------------------------------------------------------------
; STRINGS AND VARIABLES
kern_filename db "KERNEL BIN" ; MikeOS kernel filename
bootdev db 0 ; Boot device number
cluster dw 0 ; Cluster of the file we want to load
pointer dw 0 ; Pointer into Buffer, for loading kernel
;Start of our boot process
boot:
cli
xor ax, ax
mov ds, ax
mov es, ax
mov ax, 0x9000
mov ss, ax
mov sp, 0xFFFF
call enable_a20
call go_unreal
floppy_ok:
mov ax, 19
call l2hts
mov si, buffer
mov bx, ds
mov es, bx
mov bx, si
mov ah, 2
mov al, 14
pusha
read_root_dir:
popa ; In case registers are altered by int 13h
pusha
stc ; A few BIOSes do not set properly on error
int 13h ; Read sectors using BIOS
jnc search_dir ; If read went OK, skip ahead
call reset_floppy ; Otherwise, reset floppy controller and try again
jnc read_root_dir ; Floppy reset OK?
jmp reboot ; If not, fatal double error
search_dir:
popa
mov ax, ds ; Root dir is now in [buffer]
mov es, ax ; Set DI to this info
mov di, buffer
mov cx, word [RootDirEntries] ; Search all (224) entries
mov ax, 0 ; Searching at offset 0
next_root_entry:
xchg cx, dx ; We use CX in the inner loop...
mov si, kern_filename ; Start searching for kernel filename
mov cx, 11
rep cmpsb
je found_file_to_load ; Pointer DI will be at offset 11
add ax, 32 ; Bump searched entries by 1 (32 bytes per entry)
mov di, buffer ; Point to next entry
add di, ax
xchg dx, cx ; Get the original CX back
loop next_root_entry
jmp reboot
found_file_to_load: ; Fetch cluster and load FAT into RAM
mov ax, word [es:di+0Fh] ; Offset 11 + 15 = 26, contains 1st cluster
mov word [cluster], ax
mov ax, 1 ; Sector 1 = first sector of first FAT
call l2hts
mov di, buffer ; ES:BX points to our buffer
mov bx, di
mov ah, 2 ; int 13h params: read (FAT) sectors
mov al, 9 ; All 9 sectors of 1st FAT
pusha ; Prepare to enter loop
read_fat:
popa ; In case registers are altered by int 13h
pusha
stc
int 13h ; Read sectors using the BIOS
jnc read_fat_ok ; If read went OK, skip ahead
call reset_floppy ; Otherwise, reset floppy controller and try again
jnc read_fat ; Floppy reset OK?
jmp reboot ; Fatal double error
read_fat_ok:
popa
mov edi, 0x100000
mov ax, [ds:edi] ; Segment where we'll load the kernel
mov es, ax
mov bx, 0
mov ah, 2 ; int 13h floppy read params
mov al, 1
push ax ; Save in case we (or int calls) lose it
load_file_sector:
mov ax, word [cluster] ; Convert sector to logical
add ax, 31
call l2hts ; Make appropriate params for int 13h
mov ax, [ds:edi] ; Set buffer past what we've already read
mov es, ax
mov bx, word [pointer]
pop ax ; Save in case we (or int calls) lose it
push ax
stc
int 13h
jnc calculate_next_cluster ; If there's no error...
call reset_floppy ; Otherwise, reset floppy and retry
jmp load_file_sector
calculate_next_cluster:
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 the 12 bit entry
mov ax, word [ds:si]
or dx, dx ; If DX = 0 [cluster] is even; if DX = 1 then it's odd
jz even ; If [cluster] is even, drop last 4 bits of word
; with next cluster; if odd, drop first 4 bits
odd:
shr ax, 4 ; Shift out first 4 bits (they belong to another entry)
jmp short next_cluster_cont
even:
and ax, 0FFFh ; Mask out final 4 bits
next_cluster_cont:
mov word [cluster], ax ; Store cluster
cmp ax, 0FF8h ; FF8h = end of file marker in FAT12
jae end
add word [pointer], 512 ; Increase buffer pointer 1 sector length
jmp load_file_sector
end: ; We've got the file to load!
pop ax ; Clean up the stack (AX was pushed earlier)
mov dl, byte [bootdev] ; Provide kernel with boot device info
jmp 0000:0x100000 ; Jump to entry point of loaded kernel!
gdtr:
dw gdt_end - gdt_null - 1
dd gdt_null
gdt_null:
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
gdt_data:
db 0xFF, 0xFF, 0x00, 0x00, 0x00, 10010010b, 11001111b, 0x00
gdt_end:
times 510-($-$$) db 0
dw 0xAA55
buffer: