;
; Base address of the kernel
;
-KERNEL_BASE equ 0c0000000h
+LOAD_BASE equ 0200000h
;
; 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
+%define KERNEL_CS (0x8)
+%define KERNEL_DS (0x10)
+%define LOADER_CS (0x18)
+%define LOADER_DS (0x20)
+
+struc multiboot_module
+mbm_mod_start: resd 1
+mbm_mod_end: resd 1
+mbm_string: resd 1
+mbm_reserved: resd 1
+endstruc
+
+struc multiboot_address_range
+mar_baselow: resd 1
+mar_basehigh: resd 1
+mar_lengthlow: resd 1
+mar_lengthhigh: resd 1
+mar_type: resd 1
+mar_reserved: resd 3
+endstruc
;
; We are a .com program
;
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
+%define NDEBUG 1
+%macro DPRINT 1+
+%ifndef NDEBUG
+ jmp %%end_str
-;
-; 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
- ;
- mov eax,[size_div_4k]
- mov bx,[size_mod_4k]
- cmp bx,0
- je l20
- inc eax
-l20:
- shl eax,0ch
- 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
+%%str: db %1
-;
-; In: EDI = address
-; Out: FS = segment
-; DI = base
-;
-convert_to_seg:
- push eax
+%%end_str:
+ push di
+ push ds
+ push es
+ pop ds
+ mov di, %%str
+ call print_string
+ pop ds
+ pop di
+%endif
+%endmacro
- mov eax,edi
- shr eax,16
- shl eax,12
- mov fs,ax
+entry:
+ ;;
+ ;; Load stack
+ ;;
+ cli
+ push ds
+ pop ss
+ push ds
+ pop es
+ mov sp, real_stack_end
+ sti
+
+ ;;
+ ;; Setup the 32-bit registers
+ ;;
+ mov ebx, 0
+ mov eax, 0
+ mov ecx, 0
+ mov edx, 0
+ mov esi, 0
+ mov edi, 0
+
+ ;;
+ ;; Set the position for the first module to be loaded
+ ;;
+ mov dword [next_load_base], LOAD_BASE
+
+ ;;
+ ;; Setup various variables
+ ;;
+ mov bx, ds
+ movzx eax, bx
+ shl eax, 4
+ add [gdt_base], eax
+
+ ;;
+ ;; Setup the loader code and data segments
+ ;;
+ mov eax, 0
+ mov ax, cs
+ shl eax, 4
+ mov [_loader_code_base_0_15], ax
+ shr eax, 16
+ mov byte [_loader_code_base_16_23], al
+
+ mov eax, 0
+ mov ax, ds
+ shl eax, 4
+ mov [_loader_data_base_0_15], ax
+ shr eax, 16
+ mov byte [_loader_data_base_16_23], al
+
+ ;;
+ ;; load gdt
+ ;;
+ lgdt [gdt_descr]
+
+ ;;
+ ;; 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
- and edi,0ffffh
+ ;;
+ ;; Make the argument list into a c string
+ ;;
+ mov di, 081h
+ mov si, dos_cmdline
+.next_char
+ mov al, [di]
+ mov [si], al
+ cmp byte [di], 0dh
+ je .end_of_command_line
+ inc di
+ inc si
+ jmp .next_char
+
+.end_of_command_line:
+ mov byte [di], 0
+ mov byte [si], 0
+ mov [dos_cmdline_end], di
+
+ ;;
+ ;; Make the argument list into a c string
+ ;;
+ mov di, 081h
+.next_char2
+ cmp byte [di], 0
+ je .end_of_command_line2
+ cmp byte [di], ' '
+ jne .not_space
+ mov byte [di], 0
+.not_space
+ inc di
+ jmp .next_char2
+.end_of_command_line2
+
+ ;;
+ ;; Check if we want to skip the first character
+ ;;
+ cmp byte [081h], 0
+ jne .first_char_is_zero
+ mov dx, 082h
+ jmp .start_loading
+.first_char_is_zero
+ mov dx, 081h
+
+ ;;
+ ;; Check if we have reached the end of the string
+ ;;
+.start_loading
+ mov bx, dx
+ cmp byte [bx], 0
+ jne .more_modules
+ jmp .done_loading
+
+.more_modules
+ ;;
+ ;; Process the arguments
+ ;;
+ cmp byte [di], '/'
+ jne .no_next_module
+ jmp .next_module
+.no_next_module:
+
+ ;;
+ ;; Display a message saying we are loading the module
+ ;;
+ mov di, loading_msg
+ call print_string
+ mov di, dx
+ call print_string
+
+ ;;
+ ;; Save the filename
+ ;;
+ mov si, di
+ mov edx, 0
+
+ mov dx, [_multiboot_mods_count]
+ shl dx, 8
+ add dx, _multiboot_module_strings
+ mov bx, [_multiboot_mods_count]
+ imul bx, bx, multiboot_module_size
+ add bx, _multiboot_modules
+ mov eax, 0
+ mov ax, ds
+ shl eax, 4
+ add eax, edx
+ mov [bx + mbm_string], eax
+
+ mov bx, dx
+.copy_next_char
+ mov al, [si]
+ mov [bx], al
+ inc si
+ inc bx
+ cmp al, 0
+ jne .copy_next_char
+
+ ;;
+ ;; Load the file
+ ;;
+ push di
+ mov dx, di
+
+ ; Check if it is a symbol file
+ cmp byte [bx-5],'.'
+ jne .checkForHive
+ cmp byte [bx-4],'s'
+ jne .checkForHive
+ cmp byte [bx-3],'y'
+ jne .checkForHive
+ cmp byte [bx-2],'m'
+ jne .checkForHive
+
+ call sym_load_module
+ jmp .after_copy
+
+.checkForHive:
+ ; Check if it is a symbol file
+ cmp byte [bx-5],'.'
+ jne .lst_copy
+ cmp byte [bx-4],'h'
+ jne .lst_copy
+ cmp byte [bx-3],'i'
+ jne .lst_copy
+ cmp byte [bx-2],'v'
+ jne .lst_copy
+
+ call sym_load_module
+ jmp .after_copy
+
+.lst_copy:
+ ;; Check for a module list file
+ cmp byte [bx-5],'.'
+ jne .pe_copy
+ cmp byte [bx-4],'l'
+ jne .pe_copy
+ cmp byte [bx-3],'s'
+ jne .pe_copy
+ cmp byte [bx-2],'t'
+ jne .pe_copy
+
+ call sym_load_module
+
+ push es
+ mov bx,0x9000
+ push bx
+ pop es
+ xor edi,edi
+
+.lst_copy_bytes:
+ mov bx,_lst_name_local
+
+.lst_byte:
+ mov al,[es:di]
+ inc di
+ cmp al,' '
+ jg .lst_not_space
+ mov byte [bx],0
+ inc bx
+.lst_space:
+ mov al,[es:di]
+ inc di
+ cmp al,' '
+ jle .lst_space
+.lst_not_space:
+ cmp al,'*'
+ je .lst_end
+ mov [bx],al
+ inc bx
+ jmp .lst_byte
+
+.lst_end:
+ ;; We are here because the terminator was encountered
+ mov byte [bx],0 ; Zero terminate
+ inc bx
+ mov byte [bx],0
+ mov [dos_cmdline_end],bx ; Put in cmd_line_length
+ mov dx,_lst_name_local; Put this address in di
+ mov di,dx ; This, too, at the start of the
+ ; string
+
+ pop es
+
+ jmp .start_loading
+
+.pe_copy:
+ call pe_load_module
+
+.after_copy:
+ pop di
+ cmp eax, 0
+ jne .load_success
+ jmp .exit
+.load_success:
+ mov ah, 02h
+ mov dl, 0dh
+ int 021h
+ mov ah, 02h
+ mov dl, 0ah
+ int 021h
+
+ ;;
+ ;; Move onto the next module name in the command line
+ ;;
+.next_module
+ cmp di, [dos_cmdline_end]
+ je .done_loading
+ cmp byte [di], 0
+ je .found_module_name
+ inc di
+ jmp .next_module
+.found_module_name
+ inc di
+ mov dx, di
+ jmp .start_loading
+
+.done_loading
+
+ ;;
+ ;; Initialize the multiboot information
+ ;;
+ mov eax, 0
+ mov ax, ds
+ shl eax, 4
+
+ mov [_multiboot_info_base], eax
+ add dword [_multiboot_info_base], _multiboot_info
+
+ mov dword [_multiboot_flags], 0xc
+
+ mov [_multiboot_cmdline], eax
+ add dword [_multiboot_cmdline], _multiboot_kernel_cmdline
+
+ ;;
+ ;; Hide the kernel's entry in the list of modules
+ ;;
+ mov [_multiboot_mods_addr], eax
+ mov ebx, _multiboot_modules
+ add ebx, multiboot_module_size
+ add dword [_multiboot_mods_addr], ebx
+ dec dword [_multiboot_mods_count]
+
+ ;;
+ ;; get extended memory size in KB
+ ;;
+ push ebx
+ xor ebx,ebx
+ mov [_multiboot_mem_upper],ebx
+ mov [_multiboot_mem_lower],ebx
+
+ mov ax, 0xe801
+ int 015h
+ jc .oldstylemem
+
+ cmp ax, 0
+ je .cmem
+
+ and ebx, 0xffff
+ shl ebx,6
+ mov [_multiboot_mem_upper],ebx
+ and eax,0xffff
+ add dword [_multiboot_mem_upper],eax
+ jmp .done_mem
+
+.cmem:
+ cmp cx, 0
+ je .oldstylemem
+
+ and edx, 0xFFFF
+ shl edx, 6
+ mov [_multiboot_mem_upper], edx
+ and ecx, 0xFFFF
+ add dword [_multiboot_mem_upper], ecx
+ jmp .done_mem
+
+.oldstylemem:
+ ;; int 15h opt e801 don't work , try int 15h, option 88h
+ mov ah, 088h
+ int 015h
+ cmp ax, 0
+ je .cmosmem
+ mov [_multiboot_mem_upper],ax
+ jmp .done_mem
+.cmosmem:
+ ;; int 15h opt 88h don't work , try read cmos
+ xor eax,eax
+ mov al, 0x31
+ out 0x70, al
+ in al, 0x71
+ and eax, 0xffff ; clear carry
+ shl eax,8
+ mov [_multiboot_mem_upper],eax
+ xor eax,eax
+ mov al, 0x30
+ out 0x70, al
+ in al, 0x71
+ and eax, 0xffff ; clear carry
+ add [_multiboot_mem_lower],eax
+
+.done_mem:
+
+ ;;
+ ;; Retrieve BIOS memory map if available
+ ;;
+ xor ebx,ebx
+ mov edi, _multiboot_address_ranges
+
+.mmap_next:
+
+ mov edx, 'PAMS'
+ mov ecx, multiboot_address_range_size
+ mov eax, 0E820h
+ int 15h
+ jc .done_mmap
+
+ cmp eax, 'PAMS'
+ jne .done_mmap
+
+ add edi, multiboot_address_range_size
+
+ cmp ebx, 0
+ jne .mmap_next
+
+ ;;
+ ;; Prepare multiboot memory map structures
+ ;;
+
+ ;; Fill in the address descriptor size field
+ mov dword [_multiboot_address_range_descriptor_size], multiboot_address_range_size
+
+ ;; Set flag and base address and length of memory map
+ or dword [_multiboot_flags], 40h
+ mov eax, edi
+ sub eax, _multiboot_address_ranges
+ mov dword [_multiboot_mmap_length], eax
+
+ xor eax, eax
+ mov ax, ds
+ shl eax, 4
+ mov [_multiboot_mmap_addr], eax
+ add dword [_multiboot_mmap_addr], _multiboot_address_ranges
+
+.done_mmap:
+
+ pop ebx
+
+ ;;
+ ;; Begin the pmode initalization
+ ;;
+
+ ;;
+ ;; 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 50 lines
+ mov cx, 0 ; Upper left of scroll
+ mov dx, 314fh ; Lower right of scroll
+ mov bh, 1*10h+1 ; Use normal attribute on blanked lines
+ int 10h
+
+ mov dx, 0
+ mov dh, 0
+
+ mov ah, 2
+ mov bh, 0
+ int 10h
+
+ mov dx, 0
+ mov dh, 0
+
+ mov ah, 2
+ mov bh, 0
+ int 10h
+
+ mov ah, 3
+ mov bh, 0
+ int 10h
+ movzx eax, dl
+; mov [_cursorx], eax
+ movzx eax, dh
+; mov [_cursory], eax
+
+ cli
+
+ ;;
+ ;; Load the absolute address of the multiboot information structure
+ ;;
+ mov ebx, [_multiboot_info_base]
+
+ ;;
+ ;; Enter pmode and clear prefetch queue
+ ;;
+ mov eax,cr0
+ or eax,0x10001
+ 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
+
+ ;;
+ ;; Load the multiboot magic value into eax
+ ;;
+ mov eax, 0x2badb002
+
+ ;;
+ ;; Jump to start of the kernel
+ ;;
+ jmp dword KERNEL_CS:(LOAD_BASE+0x1000)
+
+ ;;
+ ;; Never get here
+ ;;
+
+.exit:
+ mov ax,04c00h
+ int 21h
- 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
+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
;
-; Handle of the currently open file
+; print_ax - print the number in the ax register
;
-file_handle dw 0
-;
-; Size of the current file mod 4k
-;
-size_mod_4k dw 0
+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
-;
-; Size of the current file divided by 4k
-;
-size_div_4k dd 0
+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
-;
-;
-;
-last_addr dw 0
+STRUC pe_doshdr
+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
+
+
+_mb_magic:
+ dd 0
+_mb_flags:
+ dd 0
+_mb_checksum:
+ dd 0
+_mb_header_addr:
+ dd 0
+_mb_load_addr:
+ dd 0
+_mb_load_end_addr:
+ dd 0
+_mb_bss_end_addr:
+ dd 0
+_mb_entry_addr:
+ dd 0
+
+_cpe_doshdr:
+ times pe_doshdr_size db 0
+_current_filehandle:
+ dw 0
+_current_size:
+ dd 0
+_current_file_size:
+ dd 0
+
+_lst_name_local:
+ times 2048 db 0
+
+ ;;
+ ;; Load a SYM file
+ ;; DS:DX = Filename
+ ;;
+sym_load_module:
+ call load_module1
+ call load_module2
+ mov edi, [next_load_base]
+ add edi, [_current_file_size]
+
+ mov eax, edi
+ test di, 0xfff
+ jz .sym_no_round
+ and di, 0xf000
+ add edi, 0x1000
+
+ ;;
+ ;; Clear unused space in the last page
+ ;;
+ mov esi, edi
+ mov ecx, edi
+ sub ecx, eax
+
+.sym_clear:
+ mov byte [esi],0
+ inc esi
+ loop .sym_clear
+
+.sym_no_round:
+
+ call load_module3
+ ret
-;
-; Generic error message
-;
-err_msg db 'Error during operation',0
-rostitle db '',0
+ ;;
+ ;; Load a PE file
+ ;; DS:DX = Filename
+ ;;
+pe_load_module:
+ call load_module1
+
+ ;;
+ ;; Read in the DOS EXE header
+ ;;
+ mov ah, 0x3f
+ mov bx, [_current_filehandle]
+ mov cx, pe_doshdr_size
+ mov dx, _cpe_doshdr
+ int 0x21
+ jnc .header_read
+ mov dx, error_file_read_failed
+ jmp error
+.header_read
+
+ ;;
+ ;; Check the DOS EXE magic
+ ;;
+ mov ax, word [_cpe_doshdr + e_magic]
+ cmp ax, 'MZ'
+ je .mz_hdr_good
+ mov dx, error_bad_mz
+ jmp error
+.mz_hdr_good
+
+ ;;
+ ;; Find the BSS size
+ ;;
+ mov ebx, dword [_multiboot_mods_count]
+ cmp ebx, 0
+ jne .not_first
+
+ mov edx, 0
+ mov ax, 0x4200
+ mov cx, 0
+ mov dx, 0x1004
+ mov bx, [_current_filehandle]
+ int 0x21
+ jnc .start_seek1
+ mov dx, error_file_seek_failed
+ jmp error
+.start_seek1:
+ mov ah, 0x3F
+ mov bx, [_current_filehandle]
+ mov cx, 32
+ mov dx, _mb_magic
+ int 0x21
+ jnc .mb_header_read
+ mov dx, error_file_read_failed
+ jmp error
+.mb_header_read:
+ jmp .first
+
+.not_first:
+ mov dword [_mb_bss_end_addr], 0
+.first:
-;
-;
-;
-loading_msg db 'Loading: ',0
-death_msg: db 'death', 0
+ call load_module2
+ call load_module3
+ ret
-filelength_lo dw 0
-filelength_hi dw 0
+load_module1:
+ ;;
+ ;; Open file
+ ;;
+ mov ax, 0x3d00
+ int 0x21
+ jnc .file_opened
+ mov dx, error_file_open_failed
+ jmp error
+.file_opened:
+
+ ;;
+ ;; Save the file handle
+ ;;
+ mov [_current_filehandle], ax
+
+ ;;
+ ;; Print space
+ ;;
+ mov ah,02h
+ mov dl,' '
+ int 021h
+
+ ;;
+ ;; Seek to the start of the file
+ ;;
+ mov ax, 0x4200
+ mov bx, [_current_filehandle]
+ mov cx, 0
+ mov dx, 0
+ int 0x21
+ jnc .seek_start
+ mov dx, error_file_seek_failed
+ jmp error
+.seek_start:
+ ret
-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
+load_module2:
+ ;;
+ ;; Seek to the end of the file to get the file size
+ ;;
+ mov edx, 0
+ mov ax, 0x4202
+ mov dx, 0
+ mov cx, 0
+ mov bx, [_current_filehandle]
+ int 0x21
+ jnc .start_end
+ mov dx, error_file_seek_failed
+ jmp error
+.start_end
+ shl edx, 16
+ mov dx, ax
+ mov [_current_size], edx
+ mov [_current_file_size], edx
+
+ mov edx, 0
+ mov ax, 0x4200
+ mov dx, 0
+ mov cx, 0
+ mov bx, [_current_filehandle]
+ int 0x21
+ jnc .start_seek
+ mov dx, error_file_seek_failed
+ jmp error
+.start_seek
+
+ mov edi, [next_load_base]
+
+.read_next:
+ cmp dword [_current_size], 32768
+ jle .read_tail
+
+ ;;
+ ;; Read in the file data
+ ;;
+ push ds
+ mov ah, 0x3f
+ mov bx, [_current_filehandle]
+ mov cx, 32768
+ mov dx, 0x9000
+ mov ds, dx
+ mov dx, 0
+ int 0x21
+ jnc .read_data_succeeded
+ pop ds
+ mov dx, error_file_read_failed
+ jmp error
+.read_data_succeeded:
+%ifndef NDEBUG
+ mov ah,02h
+ mov dl,'#'
+ int 021h
+%endif
+
+ ;;
+ ;; Copy the file data just read in to high memory
+ ;;
+ pop ds
+ mov esi, 0x90000
+ mov ecx, 32768
+ call _himem_copy
+%ifndef NDEBUG
+ mov ah,02h
+ mov dl,'$'
+ int 021h
+%else
+ mov ah,02h
+ mov dl,'.'
+ int 021h
+%endif
+
+ sub dword [_current_size], 32768
+ jmp .read_next
+
+.read_tail
+ ;;
+ ;; Read in the tailing part of the file data
+ ;;
+ push ds
+ mov eax, [_current_size]
+ mov cx, ax
+ mov ah, 0x3f
+ mov bx, [_current_filehandle]
+ mov dx, 0x9000
+ mov ds, dx
+ mov dx, 0
+ int 0x21
+ jnc .read_last_data_succeeded
+ pop ds
+ mov dx, error_file_read_failed
+ jmp error
+.read_last_data_succeeded:
+%ifndef NDEBUG
+ mov ah,02h
+ mov dl,'#'
+ int 021h
+%endif
+
+ ;;
+ ;; Copy the tailing part to high memory
+ ;;
+ pop ds
+ mov ecx, [_current_size]
+ mov esi, 0x90000
+ call _himem_copy
+%ifndef NDEBUG
+ mov ah,02h
+ mov dl,'$'
+ int 021h
+%else
+ mov ah,02h
+ mov dl,'.'
+ int 021h
+%endif
+
+ mov edx, [_mb_bss_end_addr]
+ cmp edx, 0
+ je .no_bss
+ mov edi, edx
+.no_bss:
+ test di, 0xfff
+ jz .no_round
+ and di, 0xf000
+ add edi, 0x1000
+.no_round:
+ ret
-boot_param_struct_base dd 0
+load_module3:
+ mov bx, [_multiboot_mods_count]
+ imul bx, bx, multiboot_module_size
+ add bx, _multiboot_modules
+
+ mov edx, [next_load_base]
+ mov [bx + mbm_mod_start], edx
+ mov [bx + mbm_mod_end], edi
+ mov [next_load_base], edi
+ mov dword [bx + mbm_reserved], 0
+
+ inc dword [_multiboot_mods_count]
+
+ mov eax, 1
+
+ ret
+
+ ;;
+ ;; On error print a message and return zero
+ ;;
+error:
+ mov ah, 0x9
+ int 0x21
+ mov eax, 0
+ ret
+
+ ;;
+ ;; Copy to high memory
+ ;; ARGUMENTS
+ ;; ESI = Source address
+ ;; EDI = Destination address
+ ;; ECX = Byte count
+ ;; RETURNS
+ ;; EDI = End of the destination region
+ ;; ECX = 0
+ ;;
+_himem_copy:
+ push ds ; Save DS
+ push es ; Save ES
+ push eax
+ push esi
+
+ cmp eax, 0
+ je .l3
+
+ cli ; No interrupts during pmode
+
+ mov eax, cr0 ; Entered protected mode
+ or eax, 0x1
+ mov cr0, eax
+
+ jmp .l1 ; Flush prefetch queue
+.l1:
+
+ mov eax, KERNEL_DS ; Load DS with a suitable selector
+ mov ds, ax
+ mov eax, KERNEL_DS
+ mov es, ax
+
+ cld
+ a32 rep movsb
+;.l2:
+; mov al, [esi] ; Copy the data
+; mov [edi], al
+; dec ecx
+; inc esi
+; inc edi
+; cmp ecx, 0
+; jne .l2
+
+ mov eax, cr0 ; Leave protected mode
+ and eax, 0xfffffffe
+ mov cr0, eax
+
+ jmp .l3
+.l3:
+ sti
+ pop esi
+ pop eax
+ pop es
+ pop ds
+ ret
;
-; These variables are passed to the kernel (as a structure)
+; Loading message
;
-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
-
+loading_msg db 'Loading: ',0
+
+;;
+;; Next free address in high memory
+;;
+next_load_base dd 0
+
;
; Needed for enabling the a20 address line
;
empty_8042:
- jmp $+3
- jmp $+3
- in al,064h
- test al,02h
- jnz empty_8042
+ jmp $+3
+ jmp $+3
+ in al,064h
+ test al,02h
+ jnz empty_8042
ret
;
align 8
gdt_descr:
gdt_limit:
- dw (((6+NR_TASKS)*8)-1)
+ dw (5*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,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
- 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)
+ dd _gdt
-
-;
-; Our initial stack
-;
+ ;;
+ ;; 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:
-
-
-
+ ;;
+ ;; DOS commandline buffer
+ ;;
+dos_cmdline times 256 db 0
+dos_cmdline_end dw 0
+
+ ;;
+ ;; Boot information structure
+ ;;
+_multiboot_info_base:
+ dd 0x0
+
+_multiboot_info:
+_multiboot_flags:
+ dd 0x0
+_multiboot_mem_lower:
+ dd 0x0
+_multiboot_mem_upper:
+ dd 0x0
+_multiboot_boot_device:
+ dd 0x0
+_multiboot_cmdline:
+ dd 0x0
+_multiboot_mods_count:
+ dd 0x0
+_multiboot_mods_addr:
+ dd 0x0
+_multiboot_syms:
+ times 12 db 0
+_multiboot_mmap_length:
+ dd 0x0
+_multiboot_mmap_addr:
+ dd 0x0
+_multiboot_drives_count:
+ dd 0x0
+_multiboot_drives_addr:
+ dd 0x0
+_multiboot_config_table:
+ dd 0x0
+_multiboot_boot_loader_name:
+ dd 0x0
+_multiboot_apm_table:
+ dd 0x0
+
+_multiboot_modules:
+ times (64*multiboot_module_size) db 0
+_multiboot_module_strings:
+ times (64*256) db 0
+
+_multiboot_address_range_descriptor_size dd 0
+
+_multiboot_address_ranges:
+ times (64*multiboot_address_range_size) db 0
+
+_multiboot_kernel_cmdline:
+ db 'multi(0)disk(0)rdisk(0)partition(1)\reactos /DEBUGPORT=SCREEN'
+ times 255-($-_multiboot_kernel_cmdline) db 0
+
+ ;;
+ ;; Global descriptor table
+ ;;
+_gdt:
+ dw 0x0 ; Zero descriptor
+ dw 0x0
+ dw 0x0
+ dw 0x0
+
+ dw 0xffff ; Kernel code descriptor
+ dw 0x0000
+ dw 0x9a00
+ dw 0x00cf
+
+ dw 0xffff ; Kernel data descriptor
+ dw 0x0000
+ dw 0x9200
+ dw 0x00cf
+
+ dw 0xffff ; Loader code descriptor
+_loader_code_base_0_15:
+ dw 0x0000
+_loader_code_base_16_23:
+ db 0x00
+ db 0x9a
+ dw 0x0000
+
+ dw 0xffff ; Loader data descriptor
+_loader_data_base_0_15:
+ dw 0x0000
+_loader_data_base_16_23:
+ db 0x00
+ db 0x92
+ dw 0x0000
+
+error_pmode_already:
+ db 'Error: The processor is already in protected mode'
+ db 0xa, 0xd, '$'
+error_file_open_failed:
+ db 'Error: Failed to open file'
+ db 0xa, 0xd, '$'
+error_file_seek_failed:
+ db 'Error: File seek failed'
+ db 0xa, 0xd, '$'
+error_file_read_failed:
+ db 'Error: File read failed'
+ db 0xa, 0xd, '$'
+error_coff_load_failed:
+ db 'Error: Failed to load COFF file'
+ db 0xa, 0xd, '$'
+error_bad_mz:
+ db 'Error: Bad DOS EXE magic'
+ db 0xa, 0xd, '$'