3 ; (A20 enable code and PIC reprogram from linux bootsector)
7 ; Base address of the kernel
9 KERNEL_BASE equ 0c0000000h
20 ; Space reserved in the gdt for tss descriptors
25 ; We are a .com program
67 ; Setup the loader space
77 ; Calculate the end of this module
85 ; Round up to the nearest page
91 ; Set the start of the page directory
93 mov [kernel_page_directory_base],ebx
96 ; Set the start of the continuous range of physical memory
97 ; occupied by the kernel
103 ; Calculate the start of the system page table (0xc0000000 upwards)
105 mov [system_page_table_base],ebx
109 ; Calculate the start of the page table to map the first 4mb
111 mov [lowmem_page_table_base],ebx
115 ; Set the position for the first module to be loaded
117 mov [next_load_base],ebx
120 ; Set the address of the start of kernel code
122 mov [_start_kernel],ebx
125 ; Make the argument list into a c string
139 mov [end_cmd_line],di
148 ; Process the arguments
171 ; Move onto the next module name in the command line
174 cmp di,[end_cmd_line]
187 ; Set the end of kernel memory
189 mov eax,[next_load_base]
193 ; Begin the pmode initalization
202 ; Any errors detected jump here
233 ; Print string in DS:DI
294 ; print_ax - print the number in the ax register
390 ntf_timestamp: resd 1
391 ntf_symtab_ptr: resd 1
393 ntf_opt_hdr_sz: resw 1
397 nto_mjr_lnk_vr: resb 1
398 nto_mnr_lnk_vr: resb 1
402 nto_entry_offs: resd 1
403 nto_code_offs: resd 1
404 nto_data_offs: resd 1
405 nto_image_base: resd 1
406 nto_sec_align: resd 1
407 nto_file_align: resd 1
408 nto_mjr_os_ver: resw 1
409 nto_Mnr_os_ver: resw 1
410 nto_mjr_img_vr: resw 1
411 nto_Mnr_img_vr: resw 1
412 nto_mjr_subsys: resw 1
413 nto_mnr_subsys: resw 1
419 nto_dll_chars: resw 1
420 nto_stk_res_sz: resd 1
421 nto_stk_cmt_sz: resd 1
422 nto_hp_res_sz: resd 1
423 nto_hp_cmt_sz: resd 1
424 nto_ldr_flags: resd 1
442 se_num_relocs: resw 1
448 ; pe_load_module - load a PE module into memory
452 ; [_nr_files] - total files loaded (incremented)
453 ; [next_load_base] - load base for file (updated to next loc)
454 ; [_module_lengths] - correct slot is set.
464 mov eax, [next_load_base]
466 DPRINT 'next_load_base %A', 13, 10, 0
480 ; Seek to beginning of file
483 mov bx, [file_handle]
492 ; Compute load address for PE headers
504 mov bx, [es:file_handle]
509 ; Check DOS MZ Header
512 mov ax, word [bx + e_magic]
526 mov eax, dword [bx + e_lfanew]
527 DPRINT 'lfanew %A ', 0
529 mov eax, dword [bx + nth_sig]
541 ; Get header size and bump next_load_base
543 mov eax, [bx + nto_hdr_sz]
544 DPRINT 'header size %A ', 0
545 add dword [es:next_load_base], eax
548 ; Setup section pointer
550 mov ax, [bx + ntf_num_secs]
551 DPRINT 'num sections %a', 13, 10, 0
552 mov [es:num_sections], ax
554 mov [es:cur_section], bx
555 mov [es:cur_section + 2], ds
557 ; Load each section or fill with zeroes
561 ; Compute size of data to load from file
563 mov eax, [bx + se_rawsz]
564 DPRINT 'raw size %A ', 0
569 mov [es:size_mod_4k], ax
570 and word [es:size_mod_4k], 0x0fff
572 mov dword [es:size_div_4k], eax
575 ; Seek to section offset
577 mov eax, [bx + se_raw_ofs]
578 DPRINT 'raw offset %A ', 0
583 mov bx, [es:file_handle]
590 ; Load the base pointer
592 mov edi,[es:next_load_base]
599 ; Read data in 4k chunks
603 ; Check if we have read it all
605 mov eax, [es:size_div_4k]
610 ; Make the call (dx was loaded above)
613 mov bx, [es:file_handle]
616 ; FIXME: should check return status and count
619 ; We move onto the next pointer by altering ds
624 dec word [es:size_div_4k]
629 ; Read the last section
632 mov bx, [es:file_handle]
633 mov cx, [es:size_mod_4k]
641 ; Zero out uninitialized data sections
643 lds bx, [es:cur_section]
644 mov eax, dword [bx + se_chars]
645 DPRINT 'section chars %A', 13, 10, 0
646 test dword [bx + se_chars], 0x80
650 ; Compute size of section to zero fill
652 mov eax, [bx + se_vsz]
655 mov [es:size_mod_4k], ax
656 and word [es:size_mod_4k], 0x0fff
658 mov [size_div_4k], eax
661 ; Load the base pointer
663 mov edi,[es:next_load_base]
671 ; Check if we have read it all
673 mov eax, [es:size_div_4k]
691 ; We move onto the next pointer by altering ds
696 dec word [es:size_div_4k]
701 ; Read the last section
704 mov cx, [es:size_mod_4k]
716 ; Update raw data offset in section header
718 lds bx, [es:cur_section]
719 mov eax, [es:next_load_base]
720 sub eax, [es:load_base]
721 DPRINT 'new raw offset %A ', 0
722 mov [bx + se_raw_ofs], eax
725 ; Update next_load_base
727 mov eax, [bx + se_vsz]
728 DPRINT 'scn virtual sz %A ', 0
730 add dword [es:next_load_base], eax
731 test dword [bx + se_vsz], 0xfff
733 add dword [es:next_load_base], 0x1000
736 mov eax, [es:next_load_base]
737 DPRINT 'next load base %A', 13, 10, 0
740 ; Setup for next section or exit loop
742 dec word [es:num_sections]
745 mov [es:cur_section], bx
750 ; Update module_length
752 mov eax, [es:next_load_base]
753 sub eax, [es:load_base]
754 mov esi, [es:_nr_files]
755 mov [es:_module_lengths + esi * 4], eax
757 inc dword [es:_nr_files]
771 ; Handle of the currently open file
776 ; Size of the current file mod 4k
781 ; Size of the current file divided by 4k
795 ; Generic error message
797 err_msg db 'Error during operation',10, 13, 0
798 bad_mz_msg db 'Module has bad MZ header', 10, 13, 0
799 bad_pe_msg db 'Module has bad PE header', 10, 13, 0
801 loading_msg db 'Loading: ',0
802 death_msg db 'death', 0
807 kernel_page_directory_base dd 0
808 system_page_table_base dd 0
809 lowmem_page_table_base dd 0
813 boot_param_struct_base dd 0
816 ; These variables are passed to the kernel (as a structure)
834 _end_boot_param_struct
837 ; Needed for enabling the a20 address line
853 dw (((6+NR_TASKS)*8)-1)
860 ; Setup kernel parameters
862 mov dword [_magic],0xdeadbeef
865 ; Save cursor position
867 mov ax,3 ;! Reset video mode
875 mov ax,1112h ;! Use 8x8 font
878 mov ax,1200h ;! Use alternate print screen
881 mov ah,1h ;! Define cursor (scan lines 6 to 7)
889 MOV AH,6 ;SCROLL ACTIVE PAGE UP
890 MOV AL,32H ;CLEAR 25 LINES
891 MOV CX,0H ;UPPER LEFT OF SCROLL
892 MOV DX,314FH ;LOWER RIGHT OF SCROLL
893 MOV BH,1*10h+1 ;USE NORMAL ATTRIBUTE ON BLANKED LINE
922 add eax,_boot_param_struct
923 mov [boot_param_struct_base],eax
928 ; Zero out the kernel page directory
931 mov edi,[kernel_page_directory_base]
941 ; Map in the lowmem page table (and reuse it for the identity map)
943 mov edi,[kernel_page_directory_base]
946 mov eax,[lowmem_page_table_base]
949 mov [fs:di+(0xd0000000/(1024*1024))],eax
952 ; Map the page tables from the page table
954 mov eax,[kernel_page_directory_base]
956 mov [fs:di+(0xf0000000/(1024*1024))],eax
959 ; Map in the kernel page table
961 mov eax,[system_page_table_base]
966 ; Setup the lowmem page table
968 mov edi,[lowmem_page_table_base]
974 shl eax,12 ; ebx = ebx * 4096
975 add eax,07h ; user, rw, present
976 mov [fs:edi+ebx*4],eax
982 ; Setup the system page table
984 mov edi,[system_page_table_base]
990 add edx,[_start_kernel]
998 ; Load the page directory into cr3
1000 mov eax,[kernel_page_directory_base]
1004 ; Setup various variables
1012 ; Enable the A20 address line (to allow access to over 1mb)
1015 mov al,0D1h ; command write
1018 mov al,0DFh ; A20 on
1023 ; Reprogram the PIC because they overlap the Intel defined
1026 mov al,011h ; initialization sequence
1027 out 020h,al ; send it to 8259A-1
1028 dw 0x00eb,0x00eb ; jmp $+2, jmp $+2
1029 out 0A0h,al ; and to 8259A-2
1031 mov al,040h ; start of hardware int's (0x20)
1034 mov al,048h ; start of hardware int's 2 (0x28)
1037 mov al,04h ; 8259-1 is master
1040 mov al,002h ; 8259-2 is slave
1043 mov al,01h ; 8086 mode for both
1048 mov al,0FFh ; mask off all interrupts for now
1059 add eax,real_stack_end
1060 mov [real_stack_base],eax
1061 mov esp,[real_stack_base]
1062 mov edx,[boot_param_struct_base]
1070 ; Enter pmode and clear prefetch queue
1078 ; NOTE: This must be position independant (no references to
1079 ; non absolute variables)
1083 ; Initalize segment registers
1099 ; Jump to start of 32 bit code at c0000000
1103 jmp dword KERNEL_CS:(KERNEL_BASE+0x1000)
1109 real_stack times 1024 db 0
1112 real_stack_base dd 0
1116 ; Global descriptor table
1120 dw 0 ; Zero descriptor
1125 dw 00000h ; User code descriptor
1126 dw 00000h ; base: 0h limit: 3gb
1130 dw 00000h ; User data descriptor
1131 dw 00000h ; base: 0h limit: 3gb
1140 dw 0ffffh ; Kernel code descriptor
1142 dw 09a00h ; base 0h limit 4gb
1145 dw 0ffffh ; Kernel data descriptor
1147 dw 09200h ; base 0h limit 4gb
1151 times NR_TASKS*8 db 0