kolibrios/kernel/branches/kolibri-ahci/bootloader/grub4kos.asm

297 lines
7.6 KiB
NASM
Raw Permalink Normal View History

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2014-2015. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Kolibri OS support loader for GRUB
;
; Copyright (C) Alex Nogueira Teixeira
; Copyright (C) Diamond
; Copyright (C) Dmitry Kartashov aka shurf
; Copyright (C) Serge
;
; Distributed under GPL, see file COPYING for details
;
; Version 1.0
lf = 0x0A
cr = 0x0D
use32
org 0x100000
mboot:
dd 0x1BADB002
dd 0x00010003
dd -(0x1BADB002 + 0x00010003)
dd mboot
dd 0x100000
dd __edata
dd __end
dd __start
align 16
__start:
virtual at ebp+3
.BS_OEMName rb 8
.BPB_BytsPerSec rw 1 ; bytes per sector
.BPB_SecPerClus rb 1 ; sectors per cluster
.BPB_RsvdSecCnt rw 1 ; number of reserver sectors
.BPB_NumFATs rb 1 ; count of FAT data structures
.BPB_RootEntCnt rw 1 ; count of 32-byte dir. entries (224*32 = 14 sectors)
.BPB_TotSec16 rw 1 ; count of sectors on the volume (2880 for 1.44 mbytes disk)
.BPB_Media rb 1 ; f0 - used for removable media
.BPB_FATSz16 rw 1 ; count of sectors by one copy of FAT
.BPB_SecPerTrk rw 1 ; sectors per track
.BPB_NumHeads rw 1 ; number of heads
.BPB_HiddSec rd 1 ; count of hidden sectors
.BPB_TotSec32 rd 1 ; count of sectors on the volume (if > 65535)
end virtual
cld
mov esi, mboot
mov edi, 0x80000
mov ecx, 624/4 ;magic value
rep movsd
jmp .check_mbi
org $-0x80000
align 4
.check_mbi:
cmp eax, 0x2BADB002
mov esi, sz_invboot
jne .panic
bt dword [ebx], 3
mov esi, sz_nomods
jnc .panic
mov edx, [ebx+20] ;mods_count
mov edi, [ebx+24] ;mods_addr
cmp edx, 1
mov esi, sz_nomods
jne .panic
.scan_mod:
mov ebp, [edi] ;image start
mov ecx, [edi+4] ;image end
sub ecx, ebp ;image size
cmp ecx, 512*18*80*2 ;1.44 floppy
mov esi, sz_image
jne .panic
mov [_image_start], ebp
mov [_image_size], ecx
; calculate some disk parameters
; - beginning sector of RootDir
movzx eax, word [.BPB_FATSz16]
movzx ecx, byte [.BPB_NumFATs]
mul ecx
add ax, [.BPB_RsvdSecCnt]
mov [FirstRootDirSecNum], eax
mov esi, eax
; - count of sectors in RootDir
movzx ebx, word [.BPB_BytsPerSec]
mov cl, 5 ; divide ax by 32
shr ebx, cl ; bx = directory entries per sector
movzx eax, word [.BPB_RootEntCnt]
xor edx, edx
div ebx
mov [RootDirSecs], eax
; - data start
add esi, eax ; add beginning sector of RootDir and count sectors in RootDir
mov [data_start], esi
; reading root directory
; al=count root dir sectrors !!!! TODO: al, max 255 sectors !!!!
mov eax, [FirstRootDirSecNum]
mul word [.BPB_BytsPerSec]
lea esi, [ebp+eax]
mov eax, [RootDirSecs]
mul word [.BPB_BytsPerSec]
add eax, esi ; EAX = end of root dir. in buffer pos_read_tmp
; find kernel file in root directory
.loop_find_dir_entry:
push esi
mov ecx, 11
mov edi, kernel_name
rep cmpsb ; compare es:si and es:di, cx bytes long
pop esi
je .found_kernel_file
add esi, 32 ; next dir. entry
cmp esi, eax ; end of directory
jb .loop_find_dir_entry
mov esi, sz_kernel
jmp .panic
; === KERNEL FOUND. LOADING... ===
.found_kernel_file:
movzx ecx, word [esi+01ah] ; first cluster of kernel file
; reading first FAT table
movzx eax, word [.BPB_RsvdSecCnt] ; begin first FAT abs sector number
mul word [.BPB_BytsPerSec]
lea ebx, [ebp+eax] ; FAT address
;ebx = FAT
;ecx = cluster
;esi = src
;edi = dst
;ebp = image
; copy kernel file
movzx eax, word [.BPB_BytsPerSec]
movsx edx, byte [.BPB_SecPerClus]
mul edx
shr eax, 2
mov [cluster_size], eax
mov edi, 0x10000 ;kernel base address
.copy_kernel:
; convert cluster number to sector number
mov eax, ecx ; data cluster to read
sub eax, 2
movzx edx, byte [.BPB_SecPerClus]
mul edx
add eax, [data_start]
movzx edx, word [.BPB_BytsPerSec]
mul edx
lea esi, [ebp+eax]
mov edx, ecx
mov ecx, [cluster_size]
rep movsd
mov ecx, edx
shr edx, 1
pushf
add edx, ecx ; di = bp * 1.5
mov ax, word [ebx+edx] ; read next entry from FAT-chain
popf
jc .move_4_right
and ax, 0fffh
jmp .verify_end_sector
.move_4_right:
shr ax, 4
.verify_end_sector:
cmp ax, 0ff8h ; last cluster
jae .execute_kernel
movzx ecx, ax
jmp .copy_kernel
.execute_kernel:
mov edi, 0x100000
mov esi, [_image_start]
mov ecx, [_image_size]
shr ecx, 2
rep movsd
xor eax, eax
mov ecx, 1024
rep stosd
xor ebx, ebx
xor ecx, ecx
xor edx, edx
xor esi, esi
xor edi, edi
xor ebp, ebp
xor esp, esp
lgdt [.tmp_gdt]
jmp far 0x08:.mode_16 and 0xFFFF
.panic:
mov ebx, sz_halt
mov edx, 0xb8000+160*10+2
mov ah, 0x07
.line:
mov edi, edx
.print:
lodsb
test al, al
jz .print_next
stosw
jmp .print
.print_next:
test ebx, ebx
jz ._hlt
mov esi, ebx
xor ebx, ebx
add edx, 160
jmp .line
._hlt:
hlt
jmp ._hlt
align 8
.tmp_gdt: dw 15
dd .tmp_gdt
dw 0
.code16: dw 0xFFFF
dw 0
db 8
db 10011010b
dw 0
use16
.mode_16:
mov eax, cr0
and eax, not 0x80000001
mov cr0, eax
jmp far 0x8000:.real_mode and 0xFFFF
.real_mode:
xor eax, eax
mov ds, ax
mov es, ax
mov ss, ax
mov gs, ax
mov fs, ax
jmp far 0x1000:0000
sz_invboot db 'Invalid multiboot loader magic value',0
sz_nomods db 'No image loaded',0
sz_image db 'Image size invalid',0
sz_halt db 'Halted',0
sz_kernel db cr
kernel_name db 'KERNEL MNT ?',0
org $+0x80000
__edata:
align 4
_image_start rd 1
_image_size rd 1
FirstRootDirSecNum rd 1
RootDirSecs rd 1
data_start rd 1
cluster_size rd 1
__end: