eb05d6df1a417dc8835cb34327b3cfb55eccc589
[reactos.git] / reactos / loaders / dos / loadros.asm
1 ;
2 ; Pmode setup stub
3 ; (A20 enable code and PIC reprogram from linux bootsector)
4 ;
5
6 ;
7 ; Base address of the kernel
8 ;
9 LOAD_BASE equ 0200000h
10
11 ;
12 ; Segment selectors
13 ;
14 %define KERNEL_CS (0x8)
15 %define KERNEL_DS (0x10)
16 %define LOADER_CS (0x18)
17 %define LOADER_DS (0x20)
18
19 struc multiboot_module
20 mbm_mod_start: resd 1
21 mbm_mod_end: resd 1
22 mbm_string: resd 1
23 mbm_reserved: resd 1
24 endstruc
25
26 struc multiboot_address_range
27 mar_baselow: resd 1
28 mar_basehigh: resd 1
29 mar_lengthlow: resd 1
30 mar_lengthhigh: resd 1
31 mar_type: resd 1
32 mar_reserved: resd 3
33 endstruc
34
35 ;
36 ; We are a .com program
37 ;
38 org 100h
39
40 ;
41 ; 16 bit code
42 ;
43 BITS 16
44
45 %define NDEBUG 1
46
47 %macro DPRINT 1+
48 %ifndef NDEBUG
49 jmp %%end_str
50
51 %%str: db %1
52
53 %%end_str:
54 push di
55 push ds
56 push es
57 pop ds
58 mov di, %%str
59 call print_string
60 pop ds
61 pop di
62 %endif
63 %endmacro
64
65 entry:
66 ;;
67 ;; Load stack
68 ;;
69 cli
70 push ds
71 pop ss
72 push ds
73 pop es
74 mov sp, real_stack_end
75 sti
76
77 ;;
78 ;; Setup the 32-bit registers
79 ;;
80 mov ebx, 0
81 mov eax, 0
82 mov ecx, 0
83 mov edx, 0
84 mov esi, 0
85 mov edi, 0
86
87 ;;
88 ;; Set the position for the first module to be loaded
89 ;;
90 mov dword [next_load_base], LOAD_BASE
91
92 ;;
93 ;; Setup various variables
94 ;;
95 mov bx, ds
96 movzx eax, bx
97 shl eax, 4
98 add [gdt_base], eax
99
100 ;;
101 ;; Setup the loader code and data segments
102 ;;
103 mov eax, 0
104 mov ax, cs
105 shl eax, 4
106 mov [_loader_code_base_0_15], ax
107 shr eax, 16
108 mov byte [_loader_code_base_16_23], al
109
110 mov eax, 0
111 mov ax, ds
112 shl eax, 4
113 mov [_loader_data_base_0_15], ax
114 shr eax, 16
115 mov byte [_loader_data_base_16_23], al
116
117 ;;
118 ;; load gdt
119 ;;
120 lgdt [gdt_descr]
121
122 ;;
123 ;; Enable the A20 address line (to allow access to over 1mb)
124 ;;
125 call empty_8042
126 mov al, 0D1h ; command write
127 out 064h, al
128 call empty_8042
129 mov al, 0DFh ; A20 on
130 out 060h, al
131 call empty_8042
132
133 ;;
134 ;; Make the argument list into a c string
135 ;;
136 mov di, 081h
137 mov si, _multiboot_kernel_cmdline
138 .next_char
139 mov al, [di]
140 mov [si], al
141 cmp byte [di], 0dh
142 je .end_of_command_line
143 inc di
144 inc si
145 jmp .next_char
146
147 .end_of_command_line:
148 mov byte [di], 0
149 mov byte [si], 0
150 mov [end_cmd_line], di
151
152 ;;
153 ;; Make the argument list into a c string
154 ;;
155 mov di, 081h
156 .next_char2
157 cmp byte [di], 0
158 je .end_of_command_line2
159 cmp byte [di], ' '
160 jne .not_space
161 mov byte [di], 0
162 .not_space
163 inc di
164 jmp .next_char2
165 .end_of_command_line2
166
167 ;;
168 ;; Check if we want to skip the first character
169 ;;
170 cmp byte [081h], 0
171 jne .first_char_is_zero
172 mov dx, 082h
173 jmp .start_loading
174 .first_char_is_zero
175 mov dx, 081h
176
177 ;;
178 ;; Check if we have reached the end of the string
179 ;;
180 .start_loading
181 mov bx, dx
182 cmp byte [bx], 0
183 jne .more_modules
184 jmp .done_loading
185
186 .more_modules
187 ;;
188 ;; Process the arguments
189 ;;
190 cmp byte [di], '/'
191 jne .no_next_module
192 jmp .next_module
193 .no_next_module:
194
195 ;;
196 ;; Display a message saying we are loading the module
197 ;;
198 mov di, loading_msg
199 call print_string
200 mov di, dx
201 call print_string
202
203 ;;
204 ;; Save the filename
205 ;;
206 mov si, di
207 mov edx, 0
208
209 mov dx, [_multiboot_mods_count]
210 shl dx, 8
211 add dx, _multiboot_module_strings
212 mov bx, [_multiboot_mods_count]
213 imul bx, bx, multiboot_module_size
214 add bx, _multiboot_modules
215 mov eax, 0
216 mov ax, ds
217 shl eax, 4
218 add eax, edx
219 mov [bx + mbm_string], eax
220
221 mov bx, dx
222 .copy_next_char
223 mov al, [si]
224 mov [bx], al
225 inc si
226 inc bx
227 cmp al, 0
228 jne .copy_next_char
229
230 ;;
231 ;; Load the file
232 ;;
233 push di
234 mov dx, di
235
236 ; Check if it is a symbol file
237 cmp byte [bx-5],'.'
238 jne .checkForHive
239 cmp byte [bx-4],'s'
240 jne .checkForHive
241 cmp byte [bx-3],'y'
242 jne .checkForHive
243 cmp byte [bx-2],'m'
244 jne .checkForHive
245
246 call sym_load_module
247 jmp .after_copy
248
249 .checkForHive:
250 ; Check if it is a symbol file
251 cmp byte [bx-5],'.'
252 jne .lst_copy
253 cmp byte [bx-4],'h'
254 jne .lst_copy
255 cmp byte [bx-3],'i'
256 jne .lst_copy
257 cmp byte [bx-2],'v'
258 jne .lst_copy
259
260 call sym_load_module
261 jmp .after_copy
262
263 .lst_copy:
264 ;; Check for a module list file
265 cmp byte [bx-5],'.'
266 jne .pe_copy
267 cmp byte [bx-4],'l'
268 jne .pe_copy
269 cmp byte [bx-3],'s'
270 jne .pe_copy
271 cmp byte [bx-2],'t'
272 jne .pe_copy
273
274 call sym_load_module
275
276 push es
277 mov bx,0x9000
278 push bx
279 pop es
280 xor edi,edi
281
282 .lst_copy_bytes:
283 mov bx,_lst_name_local
284
285 .lst_byte:
286 mov al,[es:di]
287 inc di
288 cmp al,' '
289 jg .lst_not_space
290 mov byte [bx],0
291 inc bx
292 .lst_space:
293 mov al,[es:di]
294 inc di
295 cmp al,' '
296 jle .lst_space
297 .lst_not_space:
298 cmp al,'*'
299 je .lst_end
300 mov [bx],al
301 inc bx
302 jmp .lst_byte
303
304 .lst_end:
305 ;; We are here because the terminator was encountered
306 mov byte [bx],0 ; Zero terminate
307 inc bx
308 mov byte [bx],0
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
312 ; string
313
314 pop es
315
316 jmp .start_loading
317
318 .pe_copy:
319 call pe_load_module
320
321 .after_copy:
322 pop di
323 cmp eax, 0
324 jne .load_success
325 jmp .exit
326 .load_success:
327 mov ah, 02h
328 mov dl, 0dh
329 int 021h
330 mov ah, 02h
331 mov dl, 0ah
332 int 021h
333
334 ;;
335 ;; Move onto the next module name in the command line
336 ;;
337 .next_module
338 cmp di, [end_cmd_line]
339 je .done_loading
340 cmp byte [di], 0
341 je .found_module_name
342 inc di
343 jmp .next_module
344 .found_module_name
345 inc di
346 mov dx, di
347 jmp .start_loading
348
349 .done_loading
350
351 ;;
352 ;; Initialize the multiboot information
353 ;;
354 mov eax, 0
355 mov ax, ds
356 shl eax, 4
357
358 mov [_multiboot_info_base], eax
359 add dword [_multiboot_info_base], _multiboot_info
360
361 mov dword [_multiboot_flags], 0xc
362
363 mov [_multiboot_cmdline], eax
364 add dword [_multiboot_cmdline], _multiboot_kernel_cmdline
365
366 ;;
367 ;; Hide the kernel's entry in the list of modules
368 ;;
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]
374
375 ;;
376 ;; get extended memory size in KB
377 ;;
378 push ebx
379 xor ebx,ebx
380 mov [_multiboot_mem_upper],ebx
381 mov [_multiboot_mem_lower],ebx
382
383 mov ax, 0xe801
384 int 015h
385 jc .oldstylemem
386
387 cmp ax, 0
388 je .cmem
389
390 and ebx, 0xffff
391 shl ebx,6
392 mov [_multiboot_mem_upper],ebx
393 and eax,0xffff
394 add dword [_multiboot_mem_upper],eax
395 jmp .done_mem
396
397 .cmem:
398 cmp cx, 0
399 je .oldstylemem
400
401 and edx, 0xFFFF
402 shl edx, 6
403 mov [_multiboot_mem_upper], edx
404 and ecx, 0xFFFF
405 add dword [_multiboot_mem_upper], ecx
406 jmp .done_mem
407
408 .oldstylemem:
409 ;; int 15h opt e801 don't work , try int 15h, option 88h
410 mov ah, 088h
411 int 015h
412 cmp ax, 0
413 je .cmosmem
414 mov [_multiboot_mem_upper],ax
415 jmp .done_mem
416 .cmosmem:
417 ;; int 15h opt 88h don't work , try read cmos
418 xor eax,eax
419 mov al, 0x31
420 out 0x70, al
421 in al, 0x71
422 and eax, 0xffff ; clear carry
423 shl eax,8
424 mov [_multiboot_mem_upper],eax
425 xor eax,eax
426 mov al, 0x30
427 out 0x70, al
428 in al, 0x71
429 and eax, 0xffff ; clear carry
430 add [_multiboot_mem_lower],eax
431
432 .done_mem:
433
434 ;;
435 ;; Retrieve BIOS memory map if available
436 ;;
437 xor ebx,ebx
438 mov edi, _multiboot_address_ranges
439
440 .mmap_next:
441
442 mov edx, 'PAMS'
443 mov ecx, multiboot_address_range_size
444 mov eax, 0E820h
445 int 15h
446 jc .done_mmap
447
448 cmp eax, 'PAMS'
449 jne .done_mmap
450
451 add edi, multiboot_address_range_size
452
453 cmp ebx, 0
454 jne .mmap_next
455
456 ;;
457 ;; Prepare multiboot memory map structures
458 ;;
459
460 ;; Fill in the address descriptor size field
461 mov dword [_multiboot_address_range_descriptor_size], multiboot_address_range_size
462
463 ;; Set flag and base address and length of memory map
464 or dword [_multiboot_flags], 40h
465 mov eax, edi
466 sub eax, _multiboot_address_ranges
467 mov dword [_multiboot_mmap_length], eax
468
469 xor eax, eax
470 mov ax, ds
471 shl eax, 4
472 mov [_multiboot_mmap_addr], eax
473 add dword [_multiboot_mmap_addr], _multiboot_address_ranges
474
475 .done_mmap:
476
477 pop ebx
478
479 ;;
480 ;; Begin the pmode initalization
481 ;;
482
483 ;;
484 ;; Save cursor position
485 ;;
486 mov ax, 3 ;! Reset video mode
487 int 10h
488
489 mov bl, 10
490 mov ah, 12
491 int 10h
492
493 mov ax, 1112h ;! Use 8x8 font
494 xor bl, bl
495 int 10h
496 mov ax, 1200h ;! Use alternate print screen
497 mov bl, 20h
498 int 10h
499 mov ah, 1h ;! Define cursor (scan lines 6 to 7)
500 mov cx, 0607h
501 int 10h
502
503 mov ah, 1
504 mov cx, 0600h
505 int 10h
506
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
512 int 10h
513
514 mov dx, 0
515 mov dh, 0
516
517 mov ah, 2
518 mov bh, 0
519 int 10h
520
521 mov dx, 0
522 mov dh, 0
523
524 mov ah, 2
525 mov bh, 0
526 int 10h
527
528 mov ah, 3
529 mov bh, 0
530 int 10h
531 movzx eax, dl
532 ; mov [_cursorx], eax
533 movzx eax, dh
534 ; mov [_cursory], eax
535
536 cli
537
538 ;;
539 ;; Load the absolute address of the multiboot information structure
540 ;;
541 mov ebx, [_multiboot_info_base]
542
543 ;;
544 ;; Enter pmode and clear prefetch queue
545 ;;
546 mov eax,cr0
547 or eax,0x10001
548 mov cr0,eax
549 jmp .next
550 .next:
551 ;;
552 ;; NOTE: This must be position independant (no references to
553 ;; non absolute variables)
554 ;;
555
556 ;;
557 ;; Initalize segment registers
558 ;;
559 mov ax,KERNEL_DS
560 mov ds,ax
561 mov ss,ax
562 mov es,ax
563 mov fs,ax
564 mov gs,ax
565
566 ;;
567 ;; Initalize eflags
568 ;;
569 push dword 0
570 popf
571
572 ;;
573 ;; Load the multiboot magic value into eax
574 ;;
575 mov eax, 0x2badb002
576
577 ;;
578 ;; Jump to start of the kernel
579 ;;
580 jmp dword KERNEL_CS:(LOAD_BASE+0x1000)
581
582 ;;
583 ;; Never get here
584 ;;
585
586 .exit:
587 mov ax,04c00h
588 int 21h
589
590 end_cmd_line dw 0
591
592 ;
593 ; Print string in DS:DI
594 ;
595 print_string:
596 push ebp
597 mov bp, sp
598 push eax
599 push edx
600 push edi
601
602 mov ax, 0x0200
603 .loop:
604 mov dl, [di]
605 cmp dl, 0
606 je .end_loop
607 cmp dl, '%'
608 jne .print_char
609 inc di
610 mov dl, [di]
611 cmp dl, 'a'
612 jne .not_ax
613 push eax
614 mov eax, [ss:bp - 4]
615 call print_ax
616 pop eax
617 jmp .next_char
618
619 .not_ax:
620 cmp dl, 'A'
621 jne .not_eax
622 push eax
623 mov eax, [ss:bp - 4]
624 call print_eax
625 pop eax
626 jmp .next_char
627
628 .not_eax:
629 cmp dl, 'c'
630 jne .not_cx
631 push ax
632 mov ax, cx
633 call print_ax
634 pop ax
635 jmp .next_char
636
637 .not_cx:
638
639 .print_char:
640 int 0x21
641
642 .next_char:
643 inc di
644 jmp .loop
645
646 .end_loop:
647 pop edi
648 pop edx
649 pop eax
650 pop ebp
651 ret
652
653 ;
654 ; print_ax - print the number in the ax register
655 ;
656
657 print_ax:
658 push ax
659 push bx
660 push cx
661 push dx
662
663 mov bx, ax
664 mov ax, 0x0200
665 mov cx, 4
666 .loop:
667 mov dx, bx
668 shr dx, 12
669 and dl, 0x0f
670 cmp dl, 0x0a
671 jge .hex_val
672 add dl, '0'
673 jmp .not_hex
674
675 .hex_val:
676 add dl, 'a' - 10
677
678 .not_hex:
679 int 0x21
680 shl bx, 4
681 dec cx
682 jnz .loop
683
684 pop dx
685 pop cx
686 pop bx
687 pop ax
688 ret
689
690 print_eax:
691 push eax
692 push ebx
693 push ecx
694 push edx
695
696 mov ebx, eax
697 mov ax, 0x0200
698 mov cx, 8
699 .loop:
700 mov edx, ebx
701 shr edx, 28
702 and dl, 0x0f
703 cmp dl, 0x0a
704 jge .hex_val
705 add dl, '0'
706 jmp .not_hex
707
708 .hex_val:
709 add dl, 'a' - 10
710
711 .not_hex:
712 int 0x21
713 shl ebx, 4
714 dec cx
715 jnz .loop
716
717 pop edx
718 pop ecx
719 pop ebx
720 pop eax
721 ret
722
723 STRUC pe_doshdr
724 e_magic: resw 1
725 e_cblp: resw 1
726 e_cp: resw 1
727 e_crlc: resw 1
728 e_cparhdr: resw 1
729 e_minalloc: resw 1
730 e_maxalloc: resw 1
731 e_ss: resw 1
732 e_sp: resw 1
733 e_csum: resw 1
734 e_ip: resw 1
735 e_cs: resw 1
736 e_lfarlc: resw 1
737 e_ovno: resw 1
738 e_res: resw 4
739 e_oemid: resw 1
740 e_oeminfo: resw 1
741 e_res2: resw 10
742 e_lfanew: resd 1
743 ENDSTRUC
744
745
746 _mb_magic:
747 dd 0
748 _mb_flags:
749 dd 0
750 _mb_checksum:
751 dd 0
752 _mb_header_addr:
753 dd 0
754 _mb_load_addr:
755 dd 0
756 _mb_load_end_addr:
757 dd 0
758 _mb_bss_end_addr:
759 dd 0
760 _mb_entry_addr:
761 dd 0
762
763 _cpe_doshdr:
764 times pe_doshdr_size db 0
765 _current_filehandle:
766 dw 0
767 _current_size:
768 dd 0
769 _current_file_size:
770 dd 0
771
772 _lst_name_local:
773 times 2048 db 0
774
775 ;;
776 ;; Load a SYM file
777 ;; DS:DX = Filename
778 ;;
779 sym_load_module:
780 call load_module1
781 call load_module2
782 mov edi, [next_load_base]
783 add edi, [_current_file_size]
784
785 mov eax, edi
786 test di, 0xfff
787 jz .sym_no_round
788 and di, 0xf000
789 add edi, 0x1000
790
791 ;;
792 ;; Clear unused space in the last page
793 ;;
794 mov esi, edi
795 mov ecx, edi
796 sub ecx, eax
797
798 .sym_clear:
799 mov byte [esi],0
800 inc esi
801 loop .sym_clear
802
803 .sym_no_round:
804
805 call load_module3
806 ret
807
808 ;;
809 ;; Load a PE file
810 ;; DS:DX = Filename
811 ;;
812 pe_load_module:
813 call load_module1
814
815 ;;
816 ;; Read in the DOS EXE header
817 ;;
818 mov ah, 0x3f
819 mov bx, [_current_filehandle]
820 mov cx, pe_doshdr_size
821 mov dx, _cpe_doshdr
822 int 0x21
823 jnc .header_read
824 mov dx, error_file_read_failed
825 jmp error
826 .header_read
827
828 ;;
829 ;; Check the DOS EXE magic
830 ;;
831 mov ax, word [_cpe_doshdr + e_magic]
832 cmp ax, 'MZ'
833 je .mz_hdr_good
834 mov dx, error_bad_mz
835 jmp error
836 .mz_hdr_good
837
838 ;;
839 ;; Find the BSS size
840 ;;
841 mov ebx, dword [_multiboot_mods_count]
842 cmp ebx, 0
843 jne .not_first
844
845 mov edx, 0
846 mov ax, 0x4200
847 mov cx, 0
848 mov dx, 0x1004
849 mov bx, [_current_filehandle]
850 int 0x21
851 jnc .start_seek1
852 mov dx, error_file_seek_failed
853 jmp error
854 .start_seek1:
855 mov ah, 0x3F
856 mov bx, [_current_filehandle]
857 mov cx, 32
858 mov dx, _mb_magic
859 int 0x21
860 jnc .mb_header_read
861 mov dx, error_file_read_failed
862 jmp error
863 .mb_header_read:
864 jmp .first
865
866 .not_first:
867 mov dword [_mb_bss_end_addr], 0
868 .first:
869
870 call load_module2
871 call load_module3
872 ret
873
874 load_module1:
875 ;;
876 ;; Open file
877 ;;
878 mov ax, 0x3d00
879 int 0x21
880 jnc .file_opened
881 mov dx, error_file_open_failed
882 jmp error
883 .file_opened:
884
885 ;;
886 ;; Save the file handle
887 ;;
888 mov [_current_filehandle], ax
889
890 ;;
891 ;; Print space
892 ;;
893 mov ah,02h
894 mov dl,' '
895 int 021h
896
897 ;;
898 ;; Seek to the start of the file
899 ;;
900 mov ax, 0x4200
901 mov bx, [_current_filehandle]
902 mov cx, 0
903 mov dx, 0
904 int 0x21
905 jnc .seek_start
906 mov dx, error_file_seek_failed
907 jmp error
908 .seek_start:
909 ret
910
911 load_module2:
912 ;;
913 ;; Seek to the end of the file to get the file size
914 ;;
915 mov edx, 0
916 mov ax, 0x4202
917 mov dx, 0
918 mov cx, 0
919 mov bx, [_current_filehandle]
920 int 0x21
921 jnc .start_end
922 mov dx, error_file_seek_failed
923 jmp error
924 .start_end
925 shl edx, 16
926 mov dx, ax
927 mov [_current_size], edx
928 mov [_current_file_size], edx
929
930 mov edx, 0
931 mov ax, 0x4200
932 mov dx, 0
933 mov cx, 0
934 mov bx, [_current_filehandle]
935 int 0x21
936 jnc .start_seek
937 mov dx, error_file_seek_failed
938 jmp error
939 .start_seek
940
941 mov edi, [next_load_base]
942
943 .read_next:
944 cmp dword [_current_size], 32768
945 jle .read_tail
946
947 ;;
948 ;; Read in the file data
949 ;;
950 push ds
951 mov ah, 0x3f
952 mov bx, [_current_filehandle]
953 mov cx, 32768
954 mov dx, 0x9000
955 mov ds, dx
956 mov dx, 0
957 int 0x21
958 jnc .read_data_succeeded
959 pop ds
960 mov dx, error_file_read_failed
961 jmp error
962 .read_data_succeeded:
963 %ifndef NDEBUG
964 mov ah,02h
965 mov dl,'#'
966 int 021h
967 %endif
968
969 ;;
970 ;; Copy the file data just read in to high memory
971 ;;
972 pop ds
973 mov esi, 0x90000
974 mov ecx, 32768
975 call _himem_copy
976 %ifndef NDEBUG
977 mov ah,02h
978 mov dl,'$'
979 int 021h
980 %else
981 mov ah,02h
982 mov dl,'.'
983 int 021h
984 %endif
985
986 sub dword [_current_size], 32768
987 jmp .read_next
988
989 .read_tail
990 ;;
991 ;; Read in the tailing part of the file data
992 ;;
993 push ds
994 mov eax, [_current_size]
995 mov cx, ax
996 mov ah, 0x3f
997 mov bx, [_current_filehandle]
998 mov dx, 0x9000
999 mov ds, dx
1000 mov dx, 0
1001 int 0x21
1002 jnc .read_last_data_succeeded
1003 pop ds
1004 mov dx, error_file_read_failed
1005 jmp error
1006 .read_last_data_succeeded:
1007 %ifndef NDEBUG
1008 mov ah,02h
1009 mov dl,'#'
1010 int 021h
1011 %endif
1012
1013 ;;
1014 ;; Copy the tailing part to high memory
1015 ;;
1016 pop ds
1017 mov ecx, [_current_size]
1018 mov esi, 0x90000
1019 call _himem_copy
1020 %ifndef NDEBUG
1021 mov ah,02h
1022 mov dl,'$'
1023 int 021h
1024 %else
1025 mov ah,02h
1026 mov dl,'.'
1027 int 021h
1028 %endif
1029
1030 mov edx, [_mb_bss_end_addr]
1031 cmp edx, 0
1032 je .no_bss
1033 mov edi, edx
1034 .no_bss:
1035 test di, 0xfff
1036 jz .no_round
1037 and di, 0xf000
1038 add edi, 0x1000
1039 .no_round:
1040 ret
1041
1042 load_module3:
1043 mov bx, [_multiboot_mods_count]
1044 imul bx, bx, multiboot_module_size
1045 add bx, _multiboot_modules
1046
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
1052
1053 inc dword [_multiboot_mods_count]
1054
1055 mov eax, 1
1056
1057 ret
1058
1059 ;;
1060 ;; On error print a message and return zero
1061 ;;
1062 error:
1063 mov ah, 0x9
1064 int 0x21
1065 mov eax, 0
1066 ret
1067
1068 ;;
1069 ;; Copy to high memory
1070 ;; ARGUMENTS
1071 ;; ESI = Source address
1072 ;; EDI = Destination address
1073 ;; ECX = Byte count
1074 ;; RETURNS
1075 ;; EDI = End of the destination region
1076 ;; ECX = 0
1077 ;;
1078 _himem_copy:
1079 push ds ; Save DS
1080 push es ; Save ES
1081 push eax
1082 push esi
1083
1084 cmp eax, 0
1085 je .l3
1086
1087 cli ; No interrupts during pmode
1088
1089 mov eax, cr0 ; Entered protected mode
1090 or eax, 0x1
1091 mov cr0, eax
1092
1093 jmp .l1 ; Flush prefetch queue
1094 .l1:
1095
1096 mov eax, KERNEL_DS ; Load DS with a suitable selector
1097 mov ds, ax
1098 mov eax, KERNEL_DS
1099 mov es, ax
1100
1101 cld
1102 a32 rep movsb
1103 ;.l2:
1104 ; mov al, [esi] ; Copy the data
1105 ; mov [edi], al
1106 ; dec ecx
1107 ; inc esi
1108 ; inc edi
1109 ; cmp ecx, 0
1110 ; jne .l2
1111
1112 mov eax, cr0 ; Leave protected mode
1113 and eax, 0xfffffffe
1114 mov cr0, eax
1115
1116 jmp .l3
1117 .l3:
1118 sti
1119 pop esi
1120 pop eax
1121 pop es
1122 pop ds
1123 ret
1124
1125 ;
1126 ; Loading message
1127 ;
1128 loading_msg db 'Loading: ',0
1129
1130 ;;
1131 ;; Next free address in high memory
1132 ;;
1133 next_load_base dd 0
1134
1135 ;
1136 ; Needed for enabling the a20 address line
1137 ;
1138 empty_8042:
1139 jmp $+3
1140 jmp $+3
1141 in al,064h
1142 test al,02h
1143 jnz empty_8042
1144 ret
1145
1146 ;
1147 ; GDT descriptor
1148 ;
1149 align 8
1150 gdt_descr:
1151 gdt_limit:
1152 dw (5*8)-1
1153 gdt_base:
1154 dd _gdt
1155
1156 ;;
1157 ;; Our initial stack
1158 ;;
1159 real_stack times 1024 db 0
1160 real_stack_end:
1161
1162 ;;
1163 ;; Boot information structure
1164 ;;
1165 _multiboot_info_base:
1166 dd 0x0
1167
1168 _multiboot_info:
1169 _multiboot_flags:
1170 dd 0x0
1171 _multiboot_mem_lower:
1172 dd 0x0
1173 _multiboot_mem_upper:
1174 dd 0x0
1175 _multiboot_boot_device:
1176 dd 0x0
1177 _multiboot_cmdline:
1178 dd 0x0
1179 _multiboot_mods_count:
1180 dd 0x0
1181 _multiboot_mods_addr:
1182 dd 0x0
1183 _multiboot_syms:
1184 times 12 db 0
1185 _multiboot_mmap_length:
1186 dd 0x0
1187 _multiboot_mmap_addr:
1188 dd 0x0
1189 _multiboot_drives_count:
1190 dd 0x0
1191 _multiboot_drives_addr:
1192 dd 0x0
1193 _multiboot_config_table:
1194 dd 0x0
1195 _multiboot_boot_loader_name:
1196 dd 0x0
1197 _multiboot_apm_table:
1198 dd 0x0
1199
1200 _multiboot_modules:
1201 times (64*multiboot_module_size) db 0
1202 _multiboot_module_strings:
1203 times (64*256) db 0
1204
1205 _multiboot_address_range_descriptor_size dd 0
1206
1207 _multiboot_address_ranges:
1208 times (64*multiboot_address_range_size) db 0
1209
1210 _multiboot_kernel_cmdline:
1211 times 255 db 0
1212
1213 ;;
1214 ;; Global descriptor table
1215 ;;
1216 _gdt:
1217 dw 0x0 ; Zero descriptor
1218 dw 0x0
1219 dw 0x0
1220 dw 0x0
1221
1222 dw 0xffff ; Kernel code descriptor
1223 dw 0x0000
1224 dw 0x9a00
1225 dw 0x00cf
1226
1227 dw 0xffff ; Kernel data descriptor
1228 dw 0x0000
1229 dw 0x9200
1230 dw 0x00cf
1231
1232 dw 0xffff ; Loader code descriptor
1233 _loader_code_base_0_15:
1234 dw 0x0000
1235 _loader_code_base_16_23:
1236 db 0x00
1237 db 0x9a
1238 dw 0x0000
1239
1240 dw 0xffff ; Loader data descriptor
1241 _loader_data_base_0_15:
1242 dw 0x0000
1243 _loader_data_base_16_23:
1244 db 0x00
1245 db 0x92
1246 dw 0x0000
1247
1248 error_pmode_already:
1249 db 'Error: The processor is already in protected mode'
1250 db 0xa, 0xd, '$'
1251 error_file_open_failed:
1252 db 'Error: Failed to open file'
1253 db 0xa, 0xd, '$'
1254 error_file_seek_failed:
1255 db 'Error: File seek failed'
1256 db 0xa, 0xd, '$'
1257 error_file_read_failed:
1258 db 'Error: File read failed'
1259 db 0xa, 0xd, '$'
1260 error_coff_load_failed:
1261 db 'Error: Failed to load COFF file'
1262 db 0xa, 0xd, '$'
1263 error_bad_mz:
1264 db 'Error: Bad DOS EXE magic'
1265 db 0xa, 0xd, '$'