diff --git a/kernel/trunk/bootloader/grub4kos.asm b/kernel/trunk/bootloader/grub4kos.asm new file mode 100644 index 0000000000..5e67abed2c --- /dev/null +++ b/kernel/trunk/bootloader/grub4kos.asm @@ -0,0 +1,276 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2014. 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 equ 0x0A +cr equ 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, 600/4 ;magic value + rep movsd + jmp .check_mbi + +org $-0x80000 +align 4 +.check_mbi: + cmp eax, 0x2BADB002 + mov ecx, sz_invboot + jne .fault + + bt dword [ebx], 3 + mov ecx, sz_nomods + jnc .fault + + mov edx, [ebx+20] ;mods_count + mov esi, [ebx+24] ;mods_addr + cmp edx, 1 + jne .fault + +.scan_mod: + mov ebp, [esi] ;image start + mov ecx, [esi+4] ;image end + sub ecx, ebp ;image size + cmp ecx, 512*18*80*2 ;1.44 floppy + jne .fault + + 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 ecx, sz_kernel + jmp .fault + + ; === 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 + +.fault: +; push ecx +; call _lcls +; call __bprintf +._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',cr,lf + db 'Halted',0 + +sz_nomods db 'No modules loaded',cr,lf + db 'Halted',0 + +sz_kernel db cr,lf +kernel_name db 'KERNEL MNT ?',cr,lf,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: