reactos/reactos/loaders/dos/loadros.asm
Rex Jolliff b5efc5cfc5 This commit was generated by cvs2svn to compensate for changes in r10,
which included commits to RCS files with non-trunk default branches.

svn path=/trunk/; revision=11
1998-08-25 04:27:41 +00:00

694 lines
14 KiB
NASM

;
; Pmode setup stub
; (A20 enable code and PIC reprogram from linux bootsector)
;
;
; Base address of the kernel
;
KERNEL_BASE equ 0c0000000h
;
; Segment selectors
;
USER_CS equ 08h
USER_DS equ 010h
KERNEL_CS equ 020h
KERNEL_DS equ 028h
;
; Space reserved in the gdt for tss descriptors
;
NR_TASKS equ 128
;
; We are a .com program
;
org 100h
;
; 16 bit code
;
BITS 16
entry:
;
; Load stack
;
cli
push ds
pop ss
mov sp,real_stack_end
sti
;
; Setup the loader space
;
mov ebx,0
mov eax,0
mov ecx,0
mov edx,0
mov esi,0
mov edi,0
;
; Calculate the end of this module
;
mov ax,ds
movzx ebx,ax
shl ebx,4
add ebx,_end
;
; Round up to the nearest page
;
and ebx,~0xfff
add ebx,01000h
;
; Set the start of the page directory
;
mov [kernel_page_directory_base],ebx
;
; Set the start of the continuous range of physical memory
; occupied by the kernel
;
mov [_start_mem],ebx
add ebx,01000h
;
; Calculate the start of the system page table (0xc0000000 upwards)
;
mov [system_page_table_base],ebx
add ebx,01000h
;
; Calculate the start of the page table to map the first 4mb
;
mov [lowmem_page_table_base],ebx
add ebx,01000h
;
; Set the position for the first module to be loaded
;
mov [next_load_base],ebx
;
; Set the address of the start of kernel code
;
mov [_start_kernel],ebx
;
; Make the argument list into a c string
;
mov di,081h
l1:
cmp byte [di],0dh
je l2
cmp byte [di],' '
jne l12
mov byte [di],0
l12:
inc di
jmp l1
l2:
mov byte [di],0
mov [end_cmd_line],di
mov dx,082h
l14:
mov bx,dx
cmp byte [bx],0
je l16
;
; Process the arguments
;
mov di,loading_msg
call _print_string
mov di,dx
call _print_string
mov ah,02h
mov dl,0dh
int 021h
mov ah,02h
mov dl,0ah
int 021h
;
; Load the file
;
push di
mov dx,di
call _load_file
pop di
;
; Move onto the next module name in the command line
;
l15:
cmp di,[end_cmd_line]
je l16
cmp byte [di],0
je l17
inc di
jmp l15
l17:
inc di
mov dx,di
jmp l14
l16:
;
; Set the end of kernel memory
;
mov eax,[next_load_base]
mov [_end_mem],eax
;
; Begin the pmode initalization
;
jmp _to_pmode
exit:
mov ax,04c00h
int 21h
;
; Any errors detected jump here
;
_error:
mov di,err_msg
call _print_string
jmp exit
end_cmd_line dw 0
;
; Read in a file to kernel_base, set kernel base to the end of the file in
; memory rounded up to the nearest page
;
; In:
; DI = filename
;
_load_file:
inc dword [_nr_files]
;
; Open the file
;
mov ah,03dh
mov al,0
mov dx,di
int 021h
jc _error
mov [file_handle],ax
;
; Find filelength
;
mov ah,042h
mov al,2
mov bx,[file_handle]
mov cx,0
mov dx,0
int 021h
;
; Convert the filelength in DX:AX to a dword in EBX
;
movzx ebx,dx
shl ebx,16
mov bx,ax
;
; Record the length of the module in boot parameter table
;
mov esi,[_nr_files]
dec esi
mov [_module_lengths+esi*4],ebx
;
; Convert the length into
;
mov [size_mod_4k],bx
and word [size_mod_4k],0fffh
shr ebx,12
mov [size_div_4k],ebx
;
; Seek to beginning of file
;
mov ah,042h
mov al,0
mov bx,[file_handle]
mov cx,0
mov dx,0
int 021h
jc _error
;
; Read in the module
;
push ds
;
; Convert the linear point to the load address into a seg:off
;
mov edi,[next_load_base]
call convert_to_seg
mov dx,di
;
; Move onto the next position in prepartion for a future read
;
movzx eax,word [size_div_4k]
inc eax
mov bx,[size_mod_4k]
cmp bx,0
je l20
inc eax
l20:
shl eax,12
add [next_load_base],eax
push fs
pop ds
;
; We read the kernel in 4k chunks (because)
;
l6:
;
; Check if we have read it all
;
mov ax,[es:size_div_4k]
cmp ax,0
je l5
;
; Make the call (dx was loaded above)
;
mov ah,3fh
mov bx,[es:file_handle]
mov cx,01000h
int 21h
;
; We move onto the next pointer by altering ds
;
mov ax,ds
add ax,0100h
mov ds,ax
dec word [es:size_div_4k]
jmp l6
l5:
;
; Read the last section
;
mov ah,3fh
mov bx,[es:file_handle]
mov cx,[es:size_mod_4k]
int 21h
pop ds
jnc _no_error
jmp _error
_no_error:
ret
;
; In: EDI = address
; Out: FS = segment
; DI = base
;
convert_to_seg:
push eax
mov eax,edi
shr eax,16
shl eax,12
mov fs,ax
and edi,0ffffh
pop eax
ret
;
; Print string in DS:DI
;
_print_string:
push ax
push dx
push di
mov ah,02h
l3:
mov dl,[di]
cmp dl,0
je l4
int 021h
inc di
jmp l3
l4:
pop di
pop dx
pop ax
ret
;
; Handle of the currently open file
;
file_handle dw 0
;
; Size of the current file mod 4k
;
size_mod_4k dw 0
;
; Size of the current file divided by 4k
;
size_div_4k dw 0
;
;
;
last_addr dw 0
;
; Generic error message
;
err_msg db 'Error during operation',0
;
;
;
loading_msg db 'Loading: ',0
filelength_lo dw 0
filelength_hi dw 0
kernel_page_directory_base dd 0
system_page_table_base dd 0
lowmem_page_table_base dd 0
next_load_base dd 0
_start_kernel dd 0
boot_param_struct_base dd 0
;
; These variables are passed to the kernel (as a structure)
;
align 4
_boot_param_struct:
_magic:
dd 0
_cursorx:
dd 0
_cursory:
dd 0
_nr_files:
dd 0
_start_mem:
dd 0
_end_mem:
dd 0
_module_lengths:
times 64 dd 0
_end_boot_param_struct
;
; Needed for enabling the a20 address line
;
empty_8042:
jmp $+3
jmp $+3
in al,064h
test al,02h
jnz empty_8042
ret
;
; GDT descriptor
;
align 8
gdt_descr:
gdt_limit:
dw (((6+NR_TASKS)*8)-1)
gdt_base:
dd gdt
_to_pmode:
;
; Setup kernel parameters
;
mov dword [_magic],0xdeadbeef
;
; Save cursor position
;
mov ah,03h
mov bh,0h
int 010h
movzx eax,dl
mov [_cursorx],eax
movzx eax,dh
mov [_cursory],eax
mov bx,ds
movzx eax,bx
shl eax,4
add eax,_boot_param_struct
mov [boot_param_struct_base],eax
cli
;
; Zero out the kernel page directory
;
;
mov edi,[kernel_page_directory_base]
call convert_to_seg
mov cx,1024
l10:
mov dword [fs:di],0
add di,4
loop l10
;
; Map in the lowmem page table (and reuse it for the identity map)
;
mov edi,[kernel_page_directory_base]
call convert_to_seg
mov eax,[lowmem_page_table_base]
add eax,07h
mov [fs:di],eax
mov [fs:di+(0xd0000000/(1024*1024))],eax
;
; Map in the kernel page table
;
mov eax,[system_page_table_base]
add eax,07h
mov [fs:di+3072],eax
;
; Setup the lowmem page table
;
mov edi,[lowmem_page_table_base]
call convert_to_seg
mov ebx,0
l9:
mov eax,ebx
shl eax,12 ; ebx = ebx * 4096
add eax,07h ; user, rw, present
mov [fs:edi+ebx*4],eax
inc ebx
cmp ebx,1024
jl l9
;
; Setup the system page table
;
mov edi,[system_page_table_base]
call convert_to_seg
mov eax,07h
l8:
mov edx,eax
add edx,[_start_kernel]
mov [fs:edi],edx
add edi,4
add eax,1000h
cmp eax,100007h
jl l8
;
; Load the page directory into cr3
;
mov eax,[kernel_page_directory_base]
mov cr3,eax
;
; Setup various variables
;
mov bx,ds
movzx eax,bx
shl eax,4
add [gdt_base],eax
;
; Enable the A20 address line (to allow access to over 1mb)
;
call empty_8042
mov al,0D1h ; command write
out 064h,al
call empty_8042
mov al,0DFh ; A20 on
out 060h,al
call empty_8042
;
; Reprogram the PIC because they overlap the Intel defined
; exceptions
;
mov al,011h ; initialization sequence
out 020h,al ; send it to 8259A-1
dw 0x00eb,0x00eb ; jmp $+2, jmp $+2
out 0A0h,al ; and to 8259A-2
dw 0x00eb,0x00eb
mov al,020h ; start of hardware int's (0x20)
out 021h,al
dw 0x00eb,0x00eb
mov al,028h ; start of hardware int's 2 (0x28)
out 0A1h,al
dw 0x00eb,0x00eb
mov al,04h ; 8259-1 is master
out 021h,al
dw 0x00eb,0x00eb
mov al,002h ; 8259-2 is slave
out 0A1h,al
dw 0x00eb,0x00eb
mov al,01h ; 8086 mode for both
out 021h,al
dw 0x00eb,0x00eb
out 0A1h,al
dw 0x00eb,0x00eb
mov al,0FFh ; mask off all interrupts for now
out 021h,al
dw 0x00eb,0x00eb
out 0A1h,al
;
; Load stack
;
mov bx,ds
movzx eax,bx
shl eax,4
add eax,real_stack_end
mov [real_stack_base],eax
mov esp,[real_stack_base]
mov edx,[boot_param_struct_base]
;
; load gdt
;
lgdt [gdt_descr]
;
; Enter pmode and clear prefetch queue
;
mov eax,cr0
or eax,0x80000001
mov cr0,eax
jmp next
next:
;
; NOTE: This must be position independant (no references to
; non absolute variables)
;
;
; Initalize segment registers
;
mov ax,KERNEL_DS
mov ds,ax
mov ss,ax
mov es,ax
mov fs,ax
;
; Initalize eflags
;
push dword 0
popf
;
; Jump to start of 32 bit code at c0000000
;
push edx
push dword 0
jmp dword KERNEL_CS:KERNEL_BASE
;
; Our initial stack
;
real_stack times 1024 db 0
real_stack_end:
real_stack_base dd 0
;
; Global descriptor table
;
align 8
gdt:
dw 0 ; Zero descriptor
dw 0
dw 0
dw 0
dw 00000h ; User code descriptor
dw 00000h ; base: 0h limit: 3gb
dw 0fa00h
dw 000cch
dw 00000h ; User data descriptor
dw 00000h ; base: 0h limit: 3gb
dw 0f200h
dw 000cch
dw 00000h
dw 00000h
dw 00000h
dw 00000h
dw 0ffffh ; Kernel code descriptor
dw 00000h ;
dw 09a00h ; base 0h limit 4gb
dw 000cfh
dw 0ffffh ; Kernel data descriptor
dw 00000h ;
dw 09200h ; base 0h limit 4gb
dw 000cfh
times NR_TASKS*8 db 0
_end: