mirror of
https://github.com/reactos/reactos.git
synced 2025-04-26 16:40:27 +00:00

which included commits to RCS files with non-trunk default branches. svn path=/trunk/; revision=11
694 lines
14 KiB
NASM
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:
|
|
|
|
|