3 ; (A20 enable code and PIC reprogram from linux bootsector)
7 ; Base address of the kernel
9 KERNEL_BASE equ 0c0000000h
23 ; Space reserved in the gdt for tss descriptors
28 ; We are a .com program
70 ; Setup the loader space
80 ; Calculate the end of this module
88 ; Round up to the nearest page
94 ; Set the start of the page directory
96 mov [kernel_page_directory_base],ebx
99 ; Set the start of the continuous range of physical memory
100 ; occupied by the kernel
106 ; Calculate the start of the system page table (0xc0000000 upwards)
108 mov [system_page_table_base],ebx
112 ; Calculate the start of the page table to map the first 4mb
114 mov [lowmem_page_table_base],ebx
118 ; Set the position for the first module to be loaded
120 mov [next_load_base],ebx
123 ; Set the address of the start of kernel code
125 mov [_start_kernel],ebx
128 ; Make the argument list into a c string
142 mov [end_cmd_line],di
151 ; Process the arguments
174 ; Move onto the next module name in the command line
177 cmp di,[end_cmd_line]
190 ; Set the end of kernel memory
192 mov eax,[next_load_base]
196 ; Begin the pmode initalization
205 ; Any errors detected jump here
236 ; Print string in DS:DI
297 ; print_ax - print the number in the ax register
393 ntf_timestamp: resd 1
394 ntf_symtab_ptr: resd 1
396 ntf_opt_hdr_sz: resw 1
400 nto_mjr_lnk_vr: resb 1
401 nto_mnr_lnk_vr: resb 1
405 nto_entry_offs: resd 1
406 nto_code_offs: resd 1
407 nto_data_offs: resd 1
408 nto_image_base: resd 1
409 nto_sec_align: resd 1
410 nto_file_align: resd 1
411 nto_mjr_os_ver: resw 1
412 nto_Mnr_os_ver: resw 1
413 nto_mjr_img_vr: resw 1
414 nto_Mnr_img_vr: resw 1
415 nto_mjr_subsys: resw 1
416 nto_mnr_subsys: resw 1
422 nto_dll_chars: resw 1
423 nto_stk_res_sz: resd 1
424 nto_stk_cmt_sz: resd 1
425 nto_hp_res_sz: resd 1
426 nto_hp_cmt_sz: resd 1
427 nto_ldr_flags: resd 1
445 se_num_relocs: resw 1
451 ; pe_load_module - load a PE module into memory
455 ; [_nr_files] - total files loaded (incremented)
456 ; [next_load_base] - load base for file (updated to next loc)
457 ; [_module_lengths] - correct slot is set.
467 mov eax, [next_load_base]
469 DPRINT 'next_load_base %A', 13, 10, 0
483 ; Seek to beginning of file
486 mov bx, [file_handle]
495 ; Compute load address for PE headers
507 mov bx, [es:file_handle]
512 ; Check DOS MZ Header
515 mov ax, word [bx + e_magic]
529 mov eax, dword [bx + e_lfanew]
530 DPRINT 'lfanew %A ', 0
532 mov eax, dword [bx + nth_sig]
544 ; Get header size and bump next_load_base
546 mov eax, [bx + nto_hdr_sz]
547 DPRINT 'header size %A ', 0
548 add dword [es:next_load_base], eax
551 ; Setup section pointer
553 mov ax, [bx + ntf_num_secs]
554 DPRINT 'num sections %a', 13, 10, 0
555 mov [es:num_sections], ax
557 mov [es:cur_section], bx
558 mov [es:cur_section + 2], ds
560 ; Load each section or fill with zeroes
564 ; Compute size of data to load from file
566 mov eax, [bx + se_rawsz]
567 DPRINT 'raw size %A ', 0
572 mov [es:size_mod_4k], ax
573 and word [es:size_mod_4k], 0x0fff
575 mov dword [es:size_div_4k], eax
578 ; Seek to section offset
580 mov eax, [bx + se_raw_ofs]
581 DPRINT 'raw offset %A ', 0
586 mov bx, [es:file_handle]
593 ; Load the base pointer
595 mov edi,[es:next_load_base]
602 ; Read data in 4k chunks
606 ; Check if we have read it all
608 mov eax, [es:size_div_4k]
613 ; Make the call (dx was loaded above)
616 mov bx, [es:file_handle]
619 ; FIXME: should check return status and count
622 ; We move onto the next pointer by altering ds
627 dec word [es:size_div_4k]
632 ; Read the last section
635 mov bx, [es:file_handle]
636 mov cx, [es:size_mod_4k]
644 ; Zero out uninitialized data sections
646 lds bx, [es:cur_section]
647 mov eax, dword [bx + se_chars]
648 DPRINT 'section chars %A', 13, 10, 0
649 test dword [bx + se_chars], 0x80
653 ; Compute size of section to zero fill
655 mov eax, [bx + se_vsz]
658 mov [es:size_mod_4k], ax
659 and word [es:size_mod_4k], 0x0fff
661 mov [size_div_4k], eax
664 ; Load the base pointer
666 mov edi,[es:next_load_base]
674 ; Check if we have read it all
676 mov eax, [es:size_div_4k]
694 ; We move onto the next pointer by altering ds
699 dec word [es:size_div_4k]
704 ; Read the last section
707 mov cx, [es:size_mod_4k]
719 ; Update raw data offset in section header
721 lds bx, [es:cur_section]
722 mov eax, [es:next_load_base]
723 sub eax, [es:load_base]
724 DPRINT 'new raw offset %A ', 0
725 mov [bx + se_raw_ofs], eax
728 ; Update next_load_base
730 mov eax, [bx + se_vsz]
731 DPRINT 'scn virtual sz %A ', 0
733 add dword [es:next_load_base], eax
734 test dword [bx + se_vsz], 0xfff
736 add dword [es:next_load_base], 0x1000
739 mov eax, [es:next_load_base]
740 DPRINT 'next load base %A', 13, 10, 0
743 ; Setup for next section or exit loop
745 dec word [es:num_sections]
748 mov [es:cur_section], bx
753 ; Update module_length
755 mov eax, [es:next_load_base]
756 sub eax, [es:load_base]
757 mov esi, [es:_nr_files]
758 mov [es:_module_lengths + esi * 4], eax
760 inc dword [es:_nr_files]
774 ; Handle of the currently open file
779 ; Size of the current file mod 4k
784 ; Size of the current file divided by 4k
798 ; Generic error message
800 err_msg db 'Error during operation',10, 13, 0
801 bad_mz_msg db 'Module has bad MZ header', 10, 13, 0
802 bad_pe_msg db 'Module has bad PE header', 10, 13, 0
804 loading_msg db 'Loading: ',0
805 death_msg db 'death', 0
810 kernel_page_directory_base dd 0
811 system_page_table_base dd 0
812 lowmem_page_table_base dd 0
816 boot_param_struct_base dd 0
819 ; These variables are passed to the kernel (as a structure)
839 _end_boot_param_struct
842 ; Needed for enabling the a20 address line
865 ; Setup kernel parameters
867 mov dword [_magic],0xdeadbeef
870 ; Save cursor position
872 mov ax,3 ;! Reset video mode
880 mov ax,1112h ;! Use 8x8 font
883 mov ax,1200h ;! Use alternate print screen
886 mov ah,1h ;! Define cursor (scan lines 6 to 7)
894 MOV AH,6 ;SCROLL ACTIVE PAGE UP
895 MOV AL,32H ;CLEAR 25 LINES
896 MOV CX,0H ;UPPER LEFT OF SCROLL
897 MOV DX,314FH ;LOWER RIGHT OF SCROLL
898 MOV BH,1*10h+1 ;USE NORMAL ATTRIBUTE ON BLANKED LINE
927 add eax,_boot_param_struct
928 mov [boot_param_struct_base],eax
933 ; Zero out the kernel page directory
936 mov edi,[kernel_page_directory_base]
946 ; Map in the lowmem page table (and reuse it for the identity map)
948 mov edi,[kernel_page_directory_base]
951 mov eax,[lowmem_page_table_base]
954 mov [fs:di+(0xd0000000/(1024*1024))],eax
957 ; Map the page tables from the page table
959 mov eax,[kernel_page_directory_base]
961 mov [fs:di+(0xf0000000/(1024*1024))],eax
964 ; Map in the kernel page table
966 mov eax,[system_page_table_base]
971 ; Setup the lowmem page table
973 mov edi,[lowmem_page_table_base]
979 shl eax,12 ; ebx = ebx * 4096
980 add eax,07h ; user, rw, present
981 mov [fs:edi+ebx*4],eax
987 ; Setup the system page table
989 mov edi,[system_page_table_base]
995 add edx,[_start_kernel]
1003 ; Load the page directory into cr3
1005 mov eax,[kernel_page_directory_base]
1009 ; Setup various variables
1017 ; Enable the A20 address line (to allow access to over 1mb)
1020 mov al,0D1h ; command write
1023 mov al,0DFh ; A20 on
1028 ; Reprogram the PIC because they overlap the Intel defined
1031 mov al,011h ; initialization sequence
1032 out 020h,al ; send it to 8259A-1
1033 dw 0x00eb,0x00eb ; jmp $+2, jmp $+2
1034 out 0A0h,al ; and to 8259A-2
1036 mov al,040h ; start of hardware int's (0x20)
1039 mov al,048h ; start of hardware int's 2 (0x28)
1042 mov al,04h ; 8259-1 is master
1045 mov al,002h ; 8259-2 is slave
1048 mov al,01h ; 8086 mode for both
1053 mov al,0FFh ; mask off all interrupts for now
1064 add eax,real_stack_end
1065 mov [real_stack_base],eax
1066 mov esp,[real_stack_base]
1067 mov edx,[boot_param_struct_base]
1075 ; Enter pmode and clear prefetch queue
1083 ; NOTE: This must be position independant (no references to
1084 ; non absolute variables)
1088 ; Initalize segment registers
1104 ; Jump to start of 32 bit code at c0000000
1108 jmp dword KERNEL_CS:(KERNEL_BASE+0x1000)
1114 real_stack times 1024 db 0
1117 real_stack_base dd 0
1121 ; Global descriptor table
1125 dw 0 ; Zero descriptor
1130 ;dw 00000h ; User code descriptor
1131 ;dw 00000h ; base: 0h limit: 3gb
1135 ;dw 00000h ; User data descriptor
1136 ;dw 00000h ; base: 0h limit: 3gb
1145 dw 0ffffh ; Kernel code descriptor
1147 dw 09a00h ; base 0h limit 4gb
1150 dw 0ffffh ; Kernel data descriptor
1152 dw 09200h ; base 0h limit 4gb
1156 ;times NR_TASKS*8 db 0