3 ; (A20 enable code and PIC reprogram from linux bootsector)
7 ; Base address of the kernel
14 %define KERNEL_CS (0x8)
15 %define KERNEL_DS (0x10)
16 %define LOADER_CS (0x18)
17 %define LOADER_DS (0x20)
19 struc multiboot_module
26 struc multiboot_address_range
30 mar_lengthhigh: resd 1
36 ; We are a .com program
74 mov sp, real_stack_end
78 ;; Setup the 32-bit registers
88 ;; Set the position for the first module to be loaded
90 mov dword [next_load_base], LOAD_BASE
93 ;; Setup various variables
101 ;; Setup the loader code and data segments
106 mov [_loader_code_base_0_15], ax
108 mov byte [_loader_code_base_16_23], al
113 mov [_loader_data_base_0_15], ax
115 mov byte [_loader_data_base_16_23], al
123 ;; Enable the A20 address line (to allow access to over 1mb)
126 mov al, 0D1h ; command write
129 mov al, 0DFh ; A20 on
134 ;; Make the argument list into a c string
137 mov si, _multiboot_kernel_cmdline
142 je .end_of_command_line
147 .end_of_command_line:
150 mov [end_cmd_line], di
153 ;; Make the argument list into a c string
158 je .end_of_command_line2
165 .end_of_command_line2
168 ;; Check if we want to skip the first character
171 jne .first_char_is_zero
178 ;; Check if we have reached the end of the string
188 ;; Process the arguments
196 ;; Display a message saying we are loading the module
209 mov dx, [_multiboot_mods_count]
211 add dx, _multiboot_module_strings
212 mov bx, [_multiboot_mods_count]
213 imul bx, bx, multiboot_module_size
214 add bx, _multiboot_modules
219 mov [bx + mbm_string], eax
236 ; Check if it is a symbol file
250 ; Check if it is a symbol file
264 ;; Check for a module list file
283 mov bx,_lst_name_local
305 ;; We are here because the terminator was encountered
306 mov byte [bx],0 ; Zero terminate
309 mov [end_cmd_line],bx ; Put in cmd_line_length
310 mov dx,_lst_name_local; Put this address in di
311 mov di,dx ; This, too, at the start of the
335 ;; Move onto the next module name in the command line
338 cmp di, [end_cmd_line]
341 je .found_module_name
352 ;; Initialize the multiboot information
358 mov [_multiboot_info_base], eax
359 add dword [_multiboot_info_base], _multiboot_info
361 mov dword [_multiboot_flags], 0xc
363 mov [_multiboot_cmdline], eax
364 add dword [_multiboot_cmdline], _multiboot_kernel_cmdline
367 ;; Hide the kernel's entry in the list of modules
369 mov [_multiboot_mods_addr], eax
370 mov ebx, _multiboot_modules
371 add ebx, multiboot_module_size
372 add dword [_multiboot_mods_addr], ebx
373 dec dword [_multiboot_mods_count]
376 ;; get extended memory size in KB
380 mov [_multiboot_mem_upper],ebx
381 mov [_multiboot_mem_lower],ebx
392 mov [_multiboot_mem_upper],ebx
394 add dword [_multiboot_mem_upper],eax
403 mov [_multiboot_mem_upper], edx
405 add dword [_multiboot_mem_upper], ecx
409 ;; int 15h opt e801 don't work , try int 15h, option 88h
414 mov [_multiboot_mem_upper],ax
417 ;; int 15h opt 88h don't work , try read cmos
422 and eax, 0xffff ; clear carry
424 mov [_multiboot_mem_upper],eax
429 and eax, 0xffff ; clear carry
430 add [_multiboot_mem_lower],eax
435 ;; Retrieve BIOS memory map if available
438 mov edi, _multiboot_address_ranges
443 mov ecx, multiboot_address_range_size
451 add edi, multiboot_address_range_size
457 ;; Prepare multiboot memory map structures
460 ;; Fill in the address descriptor size field
461 mov dword [_multiboot_address_range_descriptor_size], multiboot_address_range_size
463 ;; Set flag and base address and length of memory map
464 or dword [_multiboot_flags], 40h
466 sub eax, _multiboot_address_ranges
467 mov dword [_multiboot_mmap_length], eax
472 mov [_multiboot_mmap_addr], eax
473 add dword [_multiboot_mmap_addr], _multiboot_address_ranges
480 ;; Begin the pmode initalization
484 ;; Save cursor position
486 mov ax, 3 ;! Reset video mode
493 mov ax, 1112h ;! Use 8x8 font
496 mov ax, 1200h ;! Use alternate print screen
499 mov ah, 1h ;! Define cursor (scan lines 6 to 7)
507 mov ah, 6 ; Scroll active page up
508 mov al, 32h ; Clear 50 lines
509 mov cx, 0 ; Upper left of scroll
510 mov dx, 314fh ; Lower right of scroll
511 mov bh, 1*10h+1 ; Use normal attribute on blanked lines
532 ; mov [_cursorx], eax
534 ; mov [_cursory], eax
539 ;; Load the absolute address of the multiboot information structure
541 mov ebx, [_multiboot_info_base]
544 ;; Enter pmode and clear prefetch queue
552 ;; NOTE: This must be position independant (no references to
553 ;; non absolute variables)
557 ;; Initalize segment registers
573 ;; Load the multiboot magic value into eax
578 ;; Jump to start of the kernel
580 jmp dword KERNEL_CS:(LOAD_BASE+0x1000)
593 ; Print string in DS:DI
654 ; print_ax - print the number in the ax register
764 times pe_doshdr_size db 0
782 mov edi, [next_load_base]
783 add edi, [_current_file_size]
792 ;; Clear unused space in the last page
816 ;; Read in the DOS EXE header
819 mov bx, [_current_filehandle]
820 mov cx, pe_doshdr_size
824 mov dx, error_file_read_failed
829 ;; Check the DOS EXE magic
831 mov ax, word [_cpe_doshdr + e_magic]
841 mov ebx, dword [_multiboot_mods_count]
849 mov bx, [_current_filehandle]
852 mov dx, error_file_seek_failed
856 mov bx, [_current_filehandle]
861 mov dx, error_file_read_failed
867 mov dword [_mb_bss_end_addr], 0
881 mov dx, error_file_open_failed
886 ;; Save the file handle
888 mov [_current_filehandle], ax
898 ;; Seek to the start of the file
901 mov bx, [_current_filehandle]
906 mov dx, error_file_seek_failed
913 ;; Seek to the end of the file to get the file size
919 mov bx, [_current_filehandle]
922 mov dx, error_file_seek_failed
927 mov [_current_size], edx
928 mov [_current_file_size], edx
934 mov bx, [_current_filehandle]
937 mov dx, error_file_seek_failed
941 mov edi, [next_load_base]
944 cmp dword [_current_size], 32768
948 ;; Read in the file data
952 mov bx, [_current_filehandle]
958 jnc .read_data_succeeded
960 mov dx, error_file_read_failed
962 .read_data_succeeded:
970 ;; Copy the file data just read in to high memory
986 sub dword [_current_size], 32768
991 ;; Read in the tailing part of the file data
994 mov eax, [_current_size]
997 mov bx, [_current_filehandle]
1002 jnc .read_last_data_succeeded
1004 mov dx, error_file_read_failed
1006 .read_last_data_succeeded:
1014 ;; Copy the tailing part to high memory
1017 mov ecx, [_current_size]
1030 mov edx, [_mb_bss_end_addr]
1043 mov bx, [_multiboot_mods_count]
1044 imul bx, bx, multiboot_module_size
1045 add bx, _multiboot_modules
1047 mov edx, [next_load_base]
1048 mov [bx + mbm_mod_start], edx
1049 mov [bx + mbm_mod_end], edi
1050 mov [next_load_base], edi
1051 mov dword [bx + mbm_reserved], 0
1053 inc dword [_multiboot_mods_count]
1060 ;; On error print a message and return zero
1069 ;; Copy to high memory
1071 ;; ESI = Source address
1072 ;; EDI = Destination address
1075 ;; EDI = End of the destination region
1087 cli ; No interrupts during pmode
1089 mov eax, cr0 ; Entered protected mode
1093 jmp .l1 ; Flush prefetch queue
1096 mov eax, KERNEL_DS ; Load DS with a suitable selector
1104 ; mov al, [esi] ; Copy the data
1112 mov eax, cr0 ; Leave protected mode
1128 loading_msg db 'Loading: ',0
1131 ;; Next free address in high memory
1136 ; Needed for enabling the a20 address line
1157 ;; Our initial stack
1159 real_stack times 1024 db 0
1163 ;; Boot information structure
1165 _multiboot_info_base:
1171 _multiboot_mem_lower:
1173 _multiboot_mem_upper:
1175 _multiboot_boot_device:
1179 _multiboot_mods_count:
1181 _multiboot_mods_addr:
1185 _multiboot_mmap_length:
1187 _multiboot_mmap_addr:
1189 _multiboot_drives_count:
1191 _multiboot_drives_addr:
1193 _multiboot_config_table:
1195 _multiboot_boot_loader_name:
1197 _multiboot_apm_table:
1201 times (64*multiboot_module_size) db 0
1202 _multiboot_module_strings:
1205 _multiboot_address_range_descriptor_size dd 0
1207 _multiboot_address_ranges:
1208 times (64*multiboot_address_range_size) db 0
1210 _multiboot_kernel_cmdline:
1214 ;; Global descriptor table
1217 dw 0x0 ; Zero descriptor
1222 dw 0xffff ; Kernel code descriptor
1227 dw 0xffff ; Kernel data descriptor
1232 dw 0xffff ; Loader code descriptor
1233 _loader_code_base_0_15:
1235 _loader_code_base_16_23:
1240 dw 0xffff ; Loader data descriptor
1241 _loader_data_base_0_15:
1243 _loader_data_base_16_23:
1248 error_pmode_already:
1249 db 'Error: The processor is already in protected mode'
1251 error_file_open_failed:
1252 db 'Error: Failed to open file'
1254 error_file_seek_failed:
1255 db 'Error: File seek failed'
1257 error_file_read_failed:
1258 db 'Error: File read failed'
1260 error_coff_load_failed:
1261 db 'Error: Failed to load COFF file'
1264 db 'Error: Bad DOS EXE magic'