;***************************************************** ; $Id: loader.s,v 1.1 2002/11/25 02:07:53 rminnich Exp $ ;***************************************************** USE32 ; code it is loaded into memory at 0x7C00 ;***************************************************** nop nop ;***************************************************** ; A) setup GDT, so that we do not depend on program ; that loaded us for GDT. ; Ex: coreboot and EtherBOOT use different GDT's. ;----------------------------------------------------- ; 0) cli ;----------------------------------------------------- ; I) lgdt [0x7C00+protected_gdt] ;----------------------------------------------------- ; II) setup CS jmp 0x08:0x7C00+newpgdt newpgdt: nop ;----------------------------------------------------- ; III) setup all other segments mov ax, #0x10 mov ss, ax mov ds, ax mov es, ax mov fs, ax mov gs, ax ;----------------------------------------------------- ; IV) ; not now ;sti ;***************************************************** nop nop ;***************************************************** ; B) shadow - ON (enable/read/write) mov eax, #0x80000070 mov dx, #0x0cf8 out dx, eax mov eax, #0xFFFFFFFF mov dx, #0x0cfc out dx, eax ;***************************************************** nop nop ;***************************************************** ; C) copy -- boch bios ; counter - 64kb. mov ecx, #0x10000 ; source - 0x8000 ( 0x7C00+0x400 = 0x8000 ) mov ax, #0x10 ; src-segment - 2nd entry in GDT mov ds, ax mov eax, #0x8000 ; src-offset - 0x8000 mov esi, eax ; destination - 0xE0000 mov ax, #0x10 ; dst-segment - 2nd entry in GDT mov es, ax mov eax, #0xF0000 ; dst-offset - 0xF0000 mov edi, eax ; clear direction flag cld ; the copy rep movsb ;***************************************************** nop nop ;***************************************************** ; X) copy -- coreboot table into safe place. ;; TODO. ;; Q1 : what is the size of table. ;; Q2 : where to copy? ;***************************************************** nop nop ;***************************************************** ; E) shadow - OFF (write) mov eax, #0x80000070 mov dx, #0x0cf8 out dx, eax ;mov eax, #0xFFFFFFFF mov eax, #0x0000FFFF mov dx, #0x0cfc out dx, eax ;***************************************************** nop nop ;***************************************************** ; F) do a little prep work. ;----------------------------------------------------- ; I) disable cache ; if you disable cache, GRUB's GFX mode will be VERY slow. ; so DO NOT DISABLE ;mov eax, cr0 ;or eax, #0x60000000 ;wbinvd ;mov cr0, eax ;wbinvd ;----------------------------------------------------- ; II) disable MTRR ; clear the "E" (0x800) and "FE" (0x400) flags in ; IA32_MTRRdefType register (0x2FF) ;----------------------- ;mov ECX,#0x2FF ; select either of the two below ; depending on if your compiler suports ; {RD,WR}MSR or not ;rdmsr ; .byte 0x0F, 0x32 ;xor edx, edx ; xor eax, eax ;and eax, #0xFFFFF3FF ; select either of the two below ; depending on if your compiler suports ; {RD,WR}MSR or not ;wrmsr ; .byte 0x0F, 0x30 ;----------------------- ;; This is what PC BIOS is setting. -- P6STMT. ; add VIDEO BIOS cacheable!!!! ;----------------------- ; Fixed Range C0--C8 ;mov ECX,#0x268 ;mov EDX,#0x05050505 ;mov EAX,#0x05050505 ;wrmsr ;----------------------- ; Fixed Range C8--CF ;mov ECX,#0x269 ;mov EDX,#0x0 ;mov EAX,#0x05050505 ;wrmsr ;----------------------- ;----------------------------------------------------- ; III) tell BOCHS' BIOS we want to boot from hdd. ; 0x00 - floppy ; 0x02 - hdd ; In future there will be 'fd failover'option in bochs. mov al, #0x3d ;; cmos_reg out 0x70, al mov al, #0x02 ;; val (hdd) out 0x71, al ;----------------------------------------------------- ; IV) tell BOCHS' BIOS length of our mem block @ 1mb. ; This is for Int 15 / EAX=E820 ; 119mb = 0x77 00 00 00 ; (this is for 128mb of ram) ; (FIXME: this value is currently hard coded) ; (it should be being passed from coreboot ) ; for WinFast 6300 ; 07 70 = 0770 ; 06 80 = 0770 - 00F0 << ALT (for unpatched bochs) ; for P6STMT - 10kb less ram ; 077F - 10 = 07 6F ; 07 6F - 00 F0 = 06 7F mov al, #0x35 ;; cmos_reg out 0x70, al mov al, #0x06 ;; val out 0x71, al mov al, #0x34 ;; cmos_reg out 0x70, al mov al, #0x7F ;; val out 0x71, al mov al, #0x31 ;; cmos_reg out 0x70, al mov al, #0x00 ;; val out 0x71, al mov al, #0x30 ;; cmos_reg out 0x70, al mov al, #0x00 ;; val out 0x71, al ;----------------------------------------------------- ; V) tell BOCHS' BIOS we want to have LBA translation. ; 0x00 - NONE ; 0x01 - LBA <<<< ; 0x02 - LARGE ; 0x03 - R-CHS ; In future there will be 'fd failover'option in bochs. mov al, #0x39 ;; cmos_reg out 0x70, al mov al, #0x01 ;; val (LBA) out 0x71, al ;***************************************************** nop nop ;***************************************************** ; G) the switch -- protected to real mode ; IASDM, Vol 3 ; (8-14) 8.8.2 Switching Back to Real-Address Mode ;===================================================== ; 1) disable interrupts cli ;===================================================== nop ;===================================================== ; 2) paging ;not enabled, so not applicable. ;===================================================== ; 3) setup CS segment limit (64kb) ; I) lgdt [0x7C00+new_gdt] ;----------------------------------------------------- ; II) jmp 0x08:0x7C00+new64lim new64lim: nop ;===================================================== nop ;===================================================== ; 4) setup all other segments mov ax, #0x10 mov ss, ax mov ds, ax mov es, ax mov fs, ax mov gs, ax ;===================================================== nop ;===================================================== ; 5) LIDT ; I) ; set up Real Mode IDT table (0...3FF) ; for BOCH's BIOS the address 0xF000:0xFF53 ; cantains value 0xCF which is IRET opcode. ; counter mov cx, #0xFF ;1024 bytes(255 interrupts)(4*255=0x3FF) ; destination - 0x00000 = ES:EDI mov ax, #0x10 ; dst-segment - 2nd entry in GDT mov es, ax mov eax, #0x00000 ; dst-offset - 0x00000 mov edi, eax ; data to store -- 0xF000:FF53 mov eax, #0xF000FF53 ; clear direction flag cld ; the store rep stosd ;----------------------------------------------------- ; II) ; load interrupt descriptor table lidt [0x7C00+new_idt] ;===================================================== nop nop ;===================================================== ; 6) clear the PE flag in CR0 register. ; I) ; switch to 16 bit segments mov ax, #0x20 mov ss, ax mov ds, ax mov es, ax mov fs, ax mov gs, ax ;----------------------------------------------------- ; II) ; switch to 16 bit CS jmp 0x018:0x7C00+new16bit USE16 new16bit: nop ;----------------------------------------------------- ; III) ; the switch ;xor eax, eax mov eax, cr0 and eax, #0xFFFFFFFE mov cr0, eax ;switch to RM ;===================================================== nop nop ;===================================================== ; 7) far jump -- (to real mode address) jmp 0x0:0x7C00+realcs realcs: nop ;===================================================== ; 8) set all segment registers to 0's mov ax, #0x0 mov ss, ax mov ds, ax mov es, ax mov fs, ax mov gs, ax ;===================================================== ; 9) re-enable interrupts sti ;***************************************************** nop nop ;***************************************************** ; G) jump to BIOS. jmp 0xFFFF:0x0000 ;jmp 0xF000:0xFFF0 ;***************************************************** ;***************************************************** nop nop nop nop ;***************************************************** ;***************************************************** USE32 new_idt: dw 0x03ff ;; limit 15:00 dw 0x0000 ;; base 15:00 dw 0x0000 ;; base 23:16 new_gdt: dw 0x0028 ;; limit 15:00 dw 0x7C00+new_gdt_table ;; base 15:00 dw 0x0000 ;; base 23:16 protected_gdt: dw 0x0018 ;; limit 15:00 dw 0x7C00+pmode_gdt_table ;; base 15:00 dw 0x0000 ;; base 23:16 ;----------------------------------------------------- new_gdt_table: ;// 1 2 3 4 ;//0 dd 0x00000000 dd 0x00000000 ;//8 dd 0x0000ffff dd 0x00409E00 ;//10 dd 0x0000ffff dd 0x00409200 ;//18 dd 0x0000ffff dd 0x00009a00 ;//20 dd 0x0000ffff dd 0x00009200 ;------------------------- pmode_gdt_table: ;// 1 2 3 4 ;//0 dd 0x00000000 dd 0x00000000 ;//8 dd 0x0000ffff dd 0x00CF9E00 ;//10 dd 0x0000ffff dd 0x00CF9200 ;***************************************************** ;***************************************************** ; the file size must be 1024 bytes. .org 0x400-1 ; dd 0xdeadbeef db 0x0 ;*****************************************************