mirror of
https://github.com/reactos/reactos.git
synced 2024-05-31 17:51:49 +00:00
3ae3b46dcd
Work on security Updated heap code from wine implementation Implemented kernel/user shared data page svn path=/trunk/; revision=1297
1162 lines
21 KiB
NASM
1162 lines
21 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
|
|
|
|
KERNEL_CS equ 08h
|
|
KERNEL_DS equ 010h
|
|
|
|
;
|
|
; Space reserved in the gdt for tss descriptors
|
|
;
|
|
NR_TASKS equ 128
|
|
|
|
;
|
|
; We are a .com program
|
|
;
|
|
org 100h
|
|
|
|
;
|
|
; 16 bit code
|
|
;
|
|
BITS 16
|
|
|
|
;%define NDEBUG 1
|
|
|
|
%macro DPRINT 1+
|
|
%ifndef NDEBUG
|
|
jmp %%end_str
|
|
|
|
%%str: db %1
|
|
|
|
%%end_str:
|
|
push di
|
|
push ds
|
|
push es
|
|
pop ds
|
|
mov di, %%str
|
|
call print_string
|
|
pop ds
|
|
pop di
|
|
%endif
|
|
%endmacro
|
|
|
|
entry:
|
|
;
|
|
; Load stack
|
|
;
|
|
cli
|
|
push ds
|
|
pop ss
|
|
push ds
|
|
pop es
|
|
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
|
|
call pe_load_module
|
|
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
|
|
|
|
;
|
|
; 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
|
|
shr eax, 4
|
|
mov fs, ax
|
|
and edi, 0xf
|
|
|
|
; and edi,0ffffh
|
|
|
|
pop eax
|
|
ret
|
|
|
|
;
|
|
; Print string in DS:DI
|
|
;
|
|
print_string:
|
|
push ebp
|
|
mov bp, sp
|
|
push eax
|
|
push edx
|
|
push edi
|
|
|
|
mov ax, 0x0200
|
|
.loop:
|
|
mov dl, [di]
|
|
cmp dl, 0
|
|
je .end_loop
|
|
cmp dl, '%'
|
|
jne .print_char
|
|
inc di
|
|
mov dl, [di]
|
|
cmp dl, 'a'
|
|
jne .not_ax
|
|
push eax
|
|
mov eax, [ss:bp - 4]
|
|
call print_ax
|
|
pop eax
|
|
jmp .next_char
|
|
|
|
.not_ax:
|
|
cmp dl, 'A'
|
|
jne .not_eax
|
|
push eax
|
|
mov eax, [ss:bp - 4]
|
|
call print_eax
|
|
pop eax
|
|
jmp .next_char
|
|
|
|
.not_eax:
|
|
cmp dl, 'c'
|
|
jne .not_cx
|
|
push ax
|
|
mov ax, cx
|
|
call print_ax
|
|
pop ax
|
|
jmp .next_char
|
|
|
|
.not_cx:
|
|
|
|
.print_char:
|
|
int 0x21
|
|
|
|
.next_char:
|
|
inc di
|
|
jmp .loop
|
|
|
|
.end_loop:
|
|
pop edi
|
|
pop edx
|
|
pop eax
|
|
pop ebp
|
|
ret
|
|
|
|
;
|
|
; print_ax - print the number in the ax register
|
|
;
|
|
|
|
print_ax:
|
|
push ax
|
|
push bx
|
|
push cx
|
|
push dx
|
|
|
|
mov bx, ax
|
|
mov ax, 0x0200
|
|
mov cx, 4
|
|
.loop:
|
|
mov dx, bx
|
|
shr dx, 12
|
|
and dl, 0x0f
|
|
cmp dl, 0x0a
|
|
jge .hex_val
|
|
add dl, '0'
|
|
jmp .not_hex
|
|
|
|
.hex_val:
|
|
add dl, 'a' - 10
|
|
|
|
.not_hex:
|
|
int 0x21
|
|
shl bx, 4
|
|
dec cx
|
|
jnz .loop
|
|
|
|
pop dx
|
|
pop cx
|
|
pop bx
|
|
pop ax
|
|
ret
|
|
|
|
print_eax:
|
|
push eax
|
|
push ebx
|
|
push ecx
|
|
push edx
|
|
|
|
mov ebx, eax
|
|
mov ax, 0x0200
|
|
mov cx, 8
|
|
.loop:
|
|
mov edx, ebx
|
|
shr edx, 28
|
|
and dl, 0x0f
|
|
cmp dl, 0x0a
|
|
jge .hex_val
|
|
add dl, '0'
|
|
jmp .not_hex
|
|
|
|
.hex_val:
|
|
add dl, 'a' - 10
|
|
|
|
.not_hex:
|
|
int 0x21
|
|
shl ebx, 4
|
|
dec cx
|
|
jnz .loop
|
|
|
|
pop edx
|
|
pop ecx
|
|
pop ebx
|
|
pop eax
|
|
ret
|
|
|
|
|
|
STRUC DOS_HDR
|
|
e_magic: resw 1
|
|
e_cblp: resw 1
|
|
e_cp: resw 1
|
|
e_crlc: resw 1
|
|
e_cparhdr: resw 1
|
|
e_minalloc: resw 1
|
|
e_maxalloc: resw 1
|
|
e_ss: resw 1
|
|
e_sp: resw 1
|
|
e_csum: resw 1
|
|
e_ip: resw 1
|
|
e_cs: resw 1
|
|
e_lfarlc: resw 1
|
|
e_ovno: resw 1
|
|
e_res: resw 4
|
|
e_oemid: resw 1
|
|
e_oeminfo: resw 1
|
|
e_res2: resw 10
|
|
e_lfanew: resd 1
|
|
ENDSTRUC
|
|
|
|
STRUC NT_HDRS
|
|
nth_sig: resd 1
|
|
ntf_mach: resw 1
|
|
ntf_num_secs: resw 1
|
|
ntf_timestamp: resd 1
|
|
ntf_symtab_ptr: resd 1
|
|
ntf_num_syms: resd 1
|
|
ntf_opt_hdr_sz: resw 1
|
|
ntf_chars: resw 1
|
|
|
|
nto_magic: resw 1
|
|
nto_mjr_lnk_vr: resb 1
|
|
nto_mnr_lnk_vr: resb 1
|
|
nto_code_sz: resd 1
|
|
nto_data_sz: resd 1
|
|
nto_bss_sz: resd 1
|
|
nto_entry_offs: resd 1
|
|
nto_code_offs: resd 1
|
|
nto_data_offs: resd 1
|
|
nto_image_base: resd 1
|
|
nto_sec_align: resd 1
|
|
nto_file_align: resd 1
|
|
nto_mjr_os_ver: resw 1
|
|
nto_Mnr_os_ver: resw 1
|
|
nto_mjr_img_vr: resw 1
|
|
nto_Mnr_img_vr: resw 1
|
|
nto_mjr_subsys: resw 1
|
|
nto_mnr_subsys: resw 1
|
|
nto_w32_ver: resd 1
|
|
nto_image_sz: resd 1
|
|
nto_hdr_sz: resd 1
|
|
nto_chksum: resd 1
|
|
nto_subsys: resw 1
|
|
nto_dll_chars: resw 1
|
|
nto_stk_res_sz: resd 1
|
|
nto_stk_cmt_sz: resd 1
|
|
nto_hp_res_sz: resd 1
|
|
nto_hp_cmt_sz: resd 1
|
|
nto_ldr_flags: resd 1
|
|
nto_dir_cnt: resd 1
|
|
nto_dir_ent: resq 16
|
|
ENDSTRUC
|
|
|
|
STRUC DATA_DIR
|
|
dd_rva: resd 1
|
|
dd_sz: resd 1
|
|
ENDSTRUC
|
|
|
|
STRUC SCN_HDR
|
|
se_name: resb 8
|
|
se_vsz: resd 1
|
|
se_vaddr: resd 1
|
|
se_rawsz: resd 1
|
|
se_raw_ofs: resd 1
|
|
se_reloc_ofs: resd 1
|
|
se_lnum_ofs: resd 1
|
|
se_num_relocs: resw 1
|
|
se_num_lnums: resw 1
|
|
se_chars: resd 1
|
|
ENDSTRUC
|
|
|
|
;
|
|
; pe_load_module - load a PE module into memory
|
|
;
|
|
; DI - Filename
|
|
;
|
|
; [_nr_files] - total files loaded (incremented)
|
|
; [next_load_base] - load base for file (updated to next loc)
|
|
; [_module_lengths] - correct slot is set.
|
|
;
|
|
|
|
pe_load_module:
|
|
push dx
|
|
push ds
|
|
|
|
push ds
|
|
pop es
|
|
|
|
mov eax, [next_load_base]
|
|
mov [load_base], eax
|
|
DPRINT 'next_load_base %A', 13, 10, 0
|
|
|
|
;
|
|
; Open the file
|
|
;
|
|
mov ax, 0x3d00
|
|
mov dx, di
|
|
int 0x21
|
|
jnc .open_good
|
|
jmp .error
|
|
.open_good:
|
|
mov [file_handle],ax
|
|
|
|
;
|
|
; Seek to beginning of file
|
|
;
|
|
mov ax,0x4200
|
|
mov bx, [file_handle]
|
|
mov cx, 0
|
|
mov dx, 0
|
|
int 0x21
|
|
jnc .rewind_good
|
|
jmp .error
|
|
.rewind_good:
|
|
|
|
;
|
|
; Compute load address for PE headers
|
|
;
|
|
mov edi,[load_base]
|
|
call convert_to_seg
|
|
mov dx,di
|
|
push fs
|
|
pop ds
|
|
|
|
;
|
|
; Load the headers
|
|
;
|
|
mov ax, 0x3f00
|
|
mov bx, [es:file_handle]
|
|
mov cx, 0x1000
|
|
int 0x21
|
|
|
|
;
|
|
; Check DOS MZ Header
|
|
;
|
|
mov bx, dx
|
|
mov ax, word [bx + e_magic]
|
|
cmp ax, 'MZ'
|
|
je .mz_hdr_good
|
|
push es
|
|
pop ds
|
|
mov dx, bad_mz_msg
|
|
mov di, dx
|
|
call print_string
|
|
jmp .error
|
|
|
|
.mz_hdr_good:
|
|
;
|
|
; Check PE Header
|
|
;
|
|
mov eax, dword [bx + e_lfanew]
|
|
DPRINT 'lfanew %A ', 0
|
|
add bx, ax
|
|
mov eax, dword [bx + nth_sig]
|
|
cmp eax, 0x00004550
|
|
je .pe_hdr_good
|
|
push es
|
|
pop ds
|
|
mov dx, bad_pe_msg
|
|
mov di, dx
|
|
call print_string
|
|
jmp .error
|
|
|
|
.pe_hdr_good:
|
|
;
|
|
; Get header size and bump next_load_base
|
|
;
|
|
mov eax, [bx + nto_hdr_sz]
|
|
DPRINT 'header size %A ', 0
|
|
add dword [es:next_load_base], eax
|
|
|
|
;
|
|
; Setup section pointer
|
|
;
|
|
mov ax, [bx + ntf_num_secs]
|
|
DPRINT 'num sections %a', 13, 10, 0
|
|
mov [es:num_sections], ax
|
|
add bx, NT_HDRS_size
|
|
mov [es:cur_section], bx
|
|
mov [es:cur_section + 2], ds
|
|
;
|
|
; Load each section or fill with zeroes
|
|
;
|
|
.scn_loop:
|
|
;
|
|
; Compute size of data to load from file
|
|
;
|
|
mov eax, [bx + se_rawsz]
|
|
DPRINT 'raw size %A ', 0
|
|
cmp eax, 0
|
|
jne .got_data
|
|
jmp .no_data
|
|
.got_data:
|
|
mov [es:size_mod_4k], ax
|
|
and word [es:size_mod_4k], 0x0fff
|
|
shr eax, 12
|
|
mov dword [es:size_div_4k], eax
|
|
|
|
;
|
|
; Seek to section offset
|
|
;
|
|
mov eax, [bx + se_raw_ofs]
|
|
DPRINT 'raw offset %A ', 0
|
|
mov dx, ax
|
|
shr eax, 16
|
|
mov cx, ax
|
|
mov ax,0x4200
|
|
mov bx, [es:file_handle]
|
|
int 0x21
|
|
jnc .seek_good
|
|
jmp .error
|
|
.seek_good:
|
|
|
|
;
|
|
; Load the base pointer
|
|
;
|
|
mov edi,[es:next_load_base]
|
|
call convert_to_seg
|
|
mov dx, di
|
|
push fs
|
|
pop ds
|
|
|
|
;
|
|
; Read data in 4k chunks
|
|
;
|
|
.do_chunk:
|
|
;
|
|
; Check if we have read it all
|
|
;
|
|
mov eax, [es:size_div_4k]
|
|
cmp eax, 0
|
|
je .chunk_done
|
|
|
|
;
|
|
; Make the call (dx was loaded above)
|
|
;
|
|
mov ax, 0x3f00
|
|
mov bx, [es:file_handle]
|
|
mov cx, 0x1000
|
|
int 0x21
|
|
; FIXME: should check return status and count
|
|
|
|
;
|
|
; We move onto the next pointer by altering ds
|
|
;
|
|
mov ax, ds
|
|
add ax, 0x0100
|
|
mov ds, ax
|
|
dec word [es:size_div_4k]
|
|
jmp .do_chunk
|
|
|
|
.chunk_done:
|
|
;
|
|
; Read the last section
|
|
;
|
|
mov ax, 0x3f00
|
|
mov bx, [es:file_handle]
|
|
mov cx, [es:size_mod_4k]
|
|
int 0x21
|
|
jnc .last_read_good
|
|
jmp .error
|
|
.last_read_good:
|
|
|
|
.no_data:
|
|
;
|
|
; Zero out uninitialized data sections
|
|
;
|
|
lds bx, [es:cur_section]
|
|
mov eax, dword [bx + se_chars]
|
|
DPRINT 'section chars %A', 13, 10, 0
|
|
test dword [bx + se_chars], 0x80
|
|
jz .no_fill
|
|
|
|
;
|
|
; Compute size of section to zero fill
|
|
;
|
|
mov eax, [bx + se_vsz]
|
|
cmp eax, 0
|
|
je .no_fill
|
|
mov [es:size_mod_4k], ax
|
|
and word [es:size_mod_4k], 0x0fff
|
|
shr eax, 12
|
|
mov [size_div_4k], eax
|
|
|
|
;
|
|
; Load the base pointer
|
|
;
|
|
mov edi,[es:next_load_base]
|
|
call convert_to_seg
|
|
mov dx, di
|
|
push fs
|
|
pop ds
|
|
|
|
.do_fill:
|
|
;
|
|
; Check if we have read it all
|
|
;
|
|
mov eax, [es:size_div_4k]
|
|
cmp eax, 0
|
|
je .fill_done
|
|
|
|
;
|
|
; Zero out a chunk
|
|
;
|
|
mov ax, 0x0000
|
|
mov cx, 0x1000
|
|
push di
|
|
push es
|
|
push ds
|
|
pop es
|
|
rep stosb
|
|
pop es
|
|
pop di
|
|
|
|
;
|
|
; We move onto the next pointer by altering ds
|
|
;
|
|
mov ax, ds
|
|
add ax, 0x0100
|
|
mov ds, ax
|
|
dec word [es:size_div_4k]
|
|
jmp .do_fill
|
|
|
|
.fill_done:
|
|
;
|
|
; Read the last section
|
|
;
|
|
mov ax, 0x0000
|
|
mov cx, [es:size_mod_4k]
|
|
push di
|
|
push es
|
|
push ds
|
|
pop es
|
|
rep stosb
|
|
pop es
|
|
pop di
|
|
|
|
.no_fill:
|
|
|
|
;
|
|
; Update raw data offset in section header
|
|
;
|
|
lds bx, [es:cur_section]
|
|
mov eax, [es:next_load_base]
|
|
sub eax, [es:load_base]
|
|
DPRINT 'new raw offset %A ', 0
|
|
mov [bx + se_raw_ofs], eax
|
|
|
|
;
|
|
; Update next_load_base
|
|
;
|
|
mov eax, [bx + se_vsz]
|
|
DPRINT 'scn virtual sz %A ', 0
|
|
and eax, 0xfffff000
|
|
add dword [es:next_load_base], eax
|
|
test dword [bx + se_vsz], 0xfff
|
|
jz .even_scn
|
|
add dword [es:next_load_base], 0x1000
|
|
|
|
.even_scn:
|
|
mov eax, [es:next_load_base]
|
|
DPRINT 'next load base %A', 13, 10, 0
|
|
|
|
;
|
|
; Setup for next section or exit loop
|
|
;
|
|
dec word [es:num_sections]
|
|
jz .scn_done
|
|
add bx, SCN_HDR_size
|
|
mov [es:cur_section], bx
|
|
jmp .scn_loop
|
|
|
|
.scn_done:
|
|
;
|
|
; Update module_length
|
|
;
|
|
mov eax, [es:next_load_base]
|
|
sub eax, [es:load_base]
|
|
mov esi, [es:_nr_files]
|
|
mov [es:_module_lengths + esi * 4], eax
|
|
|
|
inc dword [es:_nr_files]
|
|
|
|
pop ds
|
|
pop dx
|
|
ret
|
|
|
|
.error:
|
|
push es
|
|
pop ds
|
|
mov di, err_msg
|
|
call print_string
|
|
jmp exit
|
|
|
|
;
|
|
; 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 dd 0
|
|
|
|
load_base dd 0
|
|
num_sections dw 0
|
|
cur_section dd 0
|
|
|
|
;
|
|
;
|
|
;
|
|
last_addr dw 0
|
|
|
|
;
|
|
; Generic error message
|
|
;
|
|
err_msg db 'Error during operation',10, 13, 0
|
|
bad_mz_msg db 'Module has bad MZ header', 10, 13, 0
|
|
bad_pe_msg db 'Module has bad PE header', 10, 13, 0
|
|
rostitle db '',0
|
|
loading_msg db 'Loading: ',0
|
|
death_msg db 'death', 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
|
|
_kernel_parameters:
|
|
times 256 db 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 (3*8)-1
|
|
gdt_base:
|
|
dd gdt
|
|
|
|
|
|
_to_pmode:
|
|
;
|
|
; Setup kernel parameters
|
|
;
|
|
mov dword [_magic],0xdeadbeef
|
|
|
|
;
|
|
; Save cursor position
|
|
;
|
|
mov ax,3 ;! Reset video mode
|
|
int 10h
|
|
|
|
|
|
mov bl,10
|
|
mov ah,12
|
|
int 10h
|
|
|
|
mov ax,1112h ;! Use 8x8 font
|
|
xor bl,bl
|
|
int 10h
|
|
mov ax,1200h ;! Use alternate print screen
|
|
mov bl,20h
|
|
int 10h
|
|
mov ah,1h ;! Define cursor (scan lines 6 to 7)
|
|
mov cx,0607h
|
|
int 10h
|
|
|
|
mov ah,1
|
|
mov cx,0600h
|
|
int 10h
|
|
|
|
MOV AH,6 ;SCROLL ACTIVE PAGE UP
|
|
MOV AL,32H ;CLEAR 25 LINES
|
|
MOV CX,0H ;UPPER LEFT OF SCROLL
|
|
MOV DX,314FH ;LOWER RIGHT OF SCROLL
|
|
MOV BH,1*10h+1 ;USE NORMAL ATTRIBUTE ON BLANKED LINE
|
|
INT 10H ;VIDEO-IO
|
|
|
|
|
|
mov dx,0
|
|
mov dh,0
|
|
|
|
mov ah,02h
|
|
mov bh,0
|
|
int 10h
|
|
|
|
mov dx,0
|
|
mov dh,0
|
|
|
|
mov ah,02h
|
|
mov bh,0
|
|
int 010h
|
|
|
|
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 the page tables from the page table
|
|
;
|
|
mov eax,[kernel_page_directory_base]
|
|
add eax,07h
|
|
mov [fs:di+(0xf0000000/(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,040h ; start of hardware int's (0x20)
|
|
out 021h,al
|
|
dw 0x00eb,0x00eb
|
|
mov al,048h ; 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,0x80010001
|
|
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
|
|
mov gs,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+0x1000)
|
|
|
|
|
|
;
|
|
; 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:
|
|
|
|
|
|
|