Added a dos command line buffer and hardcoded the kernel command line for ntoskrnl...
[reactos.git] / reactos / loaders / dos / loadros.asm
index d83f7bc..e6933c9 100644 (file)
@@ -6,20 +6,31 @@
 ;
 ; 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
@@ -31,408 +42,1104 @@ org 100h
 ;
 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
 
 ;
@@ -441,307 +1148,124 @@ empty_8042:
 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, '$'