462 lines
8.8 KiB
ArmAsm
462 lines
8.8 KiB
ArmAsm
;*****************************************************
|
|
; $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: LinuxBIOS 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 -- LinuxBIOS 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 LinuxBIOS )
|
|
|
|
; 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
|
|
|
|
;*****************************************************
|