* remove "\r" nonsense
[mascara-docs.git] / amd64 / pure64-0.5.0 / src / pure64.asm
blobb6efc7a0ee71bbe05e42bb69a3b6486e1c4bfdfb
1 ; =============================================================================
2 ; Pure64 -- a 64-bit OS loader written in Assembly for x86-64 systems
3 ; Copyright (C) 2008-2012 Return Infinity -- see LICENSE.TXT
5 ; Loaded from the first stage. Gather information about the system while
6 ; in 16-bit mode (BIOS is still accessable), setup a minimal 64-bit
7 ; enviroment, load the 64-bit kernel from the filesystem into memory and
8 ; jump to it!
9 ; =============================================================================
12 ; %define PURE64_CHAIN_LOADING
13 ; If this is defined, Pure64 will chainload the kernel attached to the end of the pure64.sys binary
14 ; Windows - copy /b pure64.sys + kernel64.sys
15 ; Unix - cat pure64.sys kernel64.sys > pure64.sys
16 ; Max size of the resulting pure64.sys is 28672 bytes
19 USE16
20 ORG 0x00008000
21 start:
22 cli ; Disable all interrupts
23 xor eax, eax
24 xor ebx, ebx
25 xor ecx, ecx
26 xor edx, edx
27 xor esi, esi
28 xor edi, edi
29 xor ebp, ebp
30 mov ds, ax
31 mov es, ax
32 mov ss, ax
33 mov fs, ax
34 mov gs, ax
35 mov esp, 0x8000 ; Set a known free location for the stack
37 align 16
38 jmp start16 ; This command will be overwritten with 'NOP's before the AP's are started
40 %include "init_smp_ap.asm" ; Our AP code is at 0x8000
42 align 16
43 db '16'
44 align 16
46 USE16
47 start16:
48 jmp 0x0000:clearcs
50 clearcs:
51 mov ax, [0x07FE] ; MBR sector is copied to 0x0600
52 cmp ax, 0xAA55 ; Check if the word at 0x07FE is set to 0xAA55 (Boot sector marker)
53 jne no_mbr
54 mov byte [cfg_mbr], 1 ; Set for booting from a disk with a MBR
55 no_mbr:
57 ; Configure serial port
58 xor dx, dx ; First serial port
59 mov ax, 0000000011100011b ; 9600 baud, no parity, 1 stop bit, 8 data bits
60 int 0x14
61 ; mov si, pure64
62 ;banner:
63 ; lodsb
64 ; cmp al, 0x00
65 ; je bannerdone
66 ; call serial_send_16
67 ; jmp banner
68 ;bannerdone:
70 ; Make sure the screen is set to 80x25 color text mode
71 mov ax, 0x0003 ; Set to normal (80x25 text) video mode
72 int 0x10
74 ; Print message
75 mov si, initStartupMsg
76 call print_string_16
78 ; Check to make sure the CPU supports 64-bit mode... If not then bail out
79 mov eax, 0x80000000 ; Extended-function 8000000h.
80 cpuid ; Is largest extended function
81 cmp eax, 0x80000000 ; any function > 80000000h?
82 jbe no_long_mode ; If not, no long mode.
83 mov eax, 0x80000001 ; Extended-function 8000001h.
84 cpuid ; Now EDX = extended-features flags.
85 bt edx, 29 ; Test if long mode is supported.
86 jnc no_long_mode ; Exit if not supported.
88 ; mov al, '0'
89 ; call serial_send_16
91 call isa_setup ; Setup legacy hardware
93 ; mov al, 'F'
94 ; call serial_send_16
96 ; At this point we are done with real mode and BIOS interrupts. Jump to 32-bit mode.
97 lgdt [cs:GDTR32] ; Load GDT register
99 ; mov al, '-'
100 ; call serial_send_16
102 mov eax, cr0
103 or al, 0x01 ; Set protected mode bit
104 mov cr0, eax
106 jmp 8:start32 ; Jump to 32-bit protected mode
108 ; 16-bit function to print a sting to the screen
109 print_string_16: ; Output string in SI to screen
110 pusha
111 mov ah, 0x0E ; int 0x10 teletype function
112 print_string_16_repeat:
113 lodsb ; Get char from string
114 cmp al, 0
115 je print_string_16_done ; If char is zero, end of string
116 int 0x10 ; Otherwise, print it
117 jmp print_string_16_repeat
118 print_string_16_done:
119 popa
122 ; 16-bit function to send a char our via serial
123 ;serial_send_16:
124 ; push edx
125 ; push eax ; Save EAX since the serial line status check clobbers AL
126 ; mov dx, 0x03FD ; Serial Line Status register
127 ;serial_send_wait_16:
128 ; in al, dx
129 ; bt ax, 5 ; Copy bit 5 (THR is empty) to the Carry Flag
130 ; jnc serial_send_wait_16 ; If the bit is not set then the queue isn't ready for another byte
131 ; pop eax ; Get the byte back from the stack
132 ; mov dx, 0x03F8 ; Serial data register
133 ; out dx, al ; Send the byte
134 ; pop edx
135 ; ret
137 ; Display an error message that the CPU does not support 64-bit mode
138 no_long_mode:
139 mov si, no64msg
140 call print_string_16
142 buffer_test:
143 in al, 0x64
144 test al, 0x01
145 jz buffer_empty
146 in al, 0x60
147 jmp buffer_test
149 buffer_empty:
150 in al, 0x64 ; wait for key pressed
151 test al, 0x01
152 jz buffer_empty
154 int 0xff ; reboot by causing a triple fault
155 jmp $
157 %include "init_isa.asm"
159 align 16
160 GDTR32: ; Global Descriptors Table Register
161 dw gdt32_end - gdt32 - 1 ; limit of GDT (size minus one)
162 dq gdt32 ; linear address of GDT
164 align 16
165 gdt32:
166 dw 0x0000, 0x0000, 0x0000, 0x0000 ; Null desciptor
167 dw 0xFFFF, 0x0000, 0x9A00, 0x00CF ; 32-bit code desciptor
168 dw 0xFFFF, 0x0000, 0x9200, 0x00CF ; 32-bit data desciptor
169 gdt32_end:
171 align 16
172 db '32'
173 align 16
176 ; =============================================================================
177 ; 32-bit mode
178 USE32
180 start32:
181 mov eax, 16 ; load 4 GB data descriptor
182 mov ds, ax ; to all data segment registers
183 mov es, ax
184 mov fs, ax
185 mov gs, ax
186 mov ss, ax
187 xor eax, eax
188 xor ebx, ebx
189 xor ecx, ecx
190 xor edx, edx
191 xor esi, esi
192 xor edi, edi
193 xor ebp, ebp
194 mov esp, 0x8000 ; Set a known free location for the stack
196 ; Debug
197 mov al, '2' ; Now in 32-bit protected mode
198 mov [0x000B809C], al
199 mov al, '0'
200 mov [0x000B809E], al
201 ; mov al, '0'
202 ; call serial_send_32
204 ; Clear out the first 4096 bytes of memory. This will store the 64-bit IDT, GDT, PML4, and PDP
205 mov ecx, 1024
206 xor eax, eax
207 mov edi, eax
208 rep stosd
210 ; Clear memory for the Page Descriptor Entries (0x10000 - 0x4FFFF)
211 mov edi, 0x00010000
212 mov ecx, 65536
213 rep stosd
215 ; Copy the GDT to its final location in memory
216 mov esi, gdt64
217 mov edi, 0x00001000 ; GDT address
218 mov ecx, (gdt64_end - gdt64)
219 rep movsb ; Move it to final pos.
221 ; Create the Level 4 Page Map. (Maps 4GBs of 2MB pages)
222 ; First create a PML4 entry.
223 ; PML4 is stored at 0x0000000000002000, create the first entry there
224 ; A single PML4 entry can map 512GB with 2MB pages.
226 mov edi, 0x00002000 ; Create a PML4 entry for the first 4GB of RAM
227 mov eax, 0x00003007
228 stosd
229 xor eax, eax
230 stosd
232 mov edi, 0x00002800 ; Create a PML4 entry for higher half (starting at 0xFFFF800000000000)
233 mov eax, 0x00003007 ; The higher half is identity mapped to the lower half
234 stosd
235 xor eax, eax
236 stosd
238 ; Create the PDP entries.
239 ; The first PDP is stored at 0x0000000000003000, create the first entries there
240 ; A single PDP entry can map 1GB with 2MB pages
241 mov ecx, 64 ; number of PDPE's to make.. each PDPE maps 1GB of physical memory
242 mov edi, 0x00003000
243 mov eax, 0x00010007 ; location of first PD
244 create_pdpe:
245 stosd
246 push eax
247 xor eax, eax
248 stosd
249 pop eax
250 add eax, 0x00001000 ; 4K later (512 records x 8 bytes)
251 dec ecx
252 cmp ecx, 0
253 jne create_pdpe
255 ; Create the PD entries.
256 ; PD entries are stored starting at 0x0000000000010000 and ending at 0x000000000004FFFF (256 KiB)
257 ; This gives us room to map 64 GiB with 2 MiB pages
258 mov edi, 0x00010000
259 mov eax, 0x0000008F ; Bit 7 must be set to 1 as we have 2 MiB pages
260 xor ecx, ecx
261 pd_again: ; Create a 2 MiB page
262 stosd
263 push eax
264 xor eax, eax
265 stosd
266 pop eax
267 add eax, 0x00200000
268 inc ecx
269 cmp ecx, 2048
270 jne pd_again ; Create 2048 2 MiB page maps.
272 ; mov al, '3'
273 ; call serial_send_32
275 ; Load the GDT
276 lgdt [GDTR64]
278 ; mov al, '4'
279 ; call serial_send_32
281 ; Enable extended properties
282 mov eax, cr4
283 or eax, 0x0000000B0 ; PGE (Bit 7), PAE (Bit 5), and PSE (Bit 4)
284 mov cr4, eax
286 ; mov al, '5'
287 ; call serial_send_32
289 ; Point cr3 at PML4
290 mov eax, 0x00002008 ; Write-thru (Bit 3)
291 mov cr3, eax
293 ; mov al, '6'
294 ; call serial_send_32
296 ; Enable long mode and SYSCALL/SYSRET
297 mov ecx, 0xC0000080 ; EFER MSR number
298 rdmsr ; Read EFER
299 or eax, 0x00000101 ; LME (Bit 8)
300 wrmsr ; Write EFER
302 ; mov al, '7'
303 ; call serial_send_32
305 ; Debug
306 mov al, '1' ; About to make the jump into 64-bit mode
307 mov [0x000B809C], al
308 mov al, 'E'
309 mov [0x000B809E], al
311 ; mov al, '-'
312 ; call serial_send_32
314 ; Enable paging to activate long mode
315 mov eax, cr0
316 or eax, 0x80000000 ; PG (Bit 31)
317 mov cr0, eax
319 jmp SYS64_CODE_SEL:start64 ; Jump to 64-bit mode
321 ; 32-bit function to send a char our via serial
322 ;serial_send_32:
323 ; push edx
324 ; push eax ; Save EAX since the serial line status check clobbers AL
325 ; mov dx, 0x03FD ; Serial Line Status register
326 ;serial_send_wait_32:
327 ; in al, dx
328 ; bt ax, 5 ; Copy bit 5 (THR is empty) to the Carry Flag
329 ; jnc serial_send_wait_32 ; If the bit is not set then the queue isn't ready for another byte
330 ; pop eax ; Get the byte back from the stack
331 ; mov dx, 0x03F8 ; Serial data register
332 ; out dx, al ; Send the byte
333 ; pop edx
334 ; ret
336 align 16
337 db '64'
338 align 16
341 ; =============================================================================
342 ; 64-bit mode
343 USE64
345 start64:
346 ; Debug
347 mov al, '4' ; Now in 64-bit mode
348 mov [0x000B809C], al
349 mov al, '0'
350 mov [0x000B809E], al
351 ; mov al, '0'
352 ; call serial_send_64
354 mov al, 2
355 mov ah, 22
356 call os_move_cursor
358 xor rax, rax ; aka r0
359 xor rbx, rbx ; aka r3
360 xor rcx, rcx ; aka r1
361 xor rdx, rdx ; aka r2
362 xor rsi, rsi ; aka r6
363 xor rdi, rdi ; aka r7
364 xor rbp, rbp ; aka r5
365 mov rsp, 0x8000 ; aka r4
366 xor r8, r8
367 xor r9, r9
368 xor r10, r10
369 xor r11, r11
370 xor r12, r12
371 xor r13, r13
372 xor r14, r14
373 xor r15, r15
375 mov ds, ax ; Clear the legacy segment registers
376 mov es, ax
377 mov ss, ax
378 mov fs, ax
379 mov gs, ax
381 mov rax, clearcs64 ; Do a proper 64-bit jump. Should not be needed as the ...
382 jmp rax ; ... jmp SYS64_CODE_SEL:start64 would have sent us ...
383 nop ; .. out of compatibilty mode and into 64-bit mode
384 clearcs64:
385 xor rax, rax
387 lgdt [GDTR64] ; Reload the GDT
389 ; Debug
390 mov al, '2'
391 mov [0x000B809E], al
392 ; mov al, '2'
393 ; call serial_send_64
395 ; Patch Pure64 AP code ; The AP's will be told to start execution at 0x8000
396 mov edi, 0x00008030 ; We need to remove the BSP Jump call to get the AP's
397 mov eax, 0x90909090 ; to fall through to the AP Init code
398 stosd
400 ; Build the rest of the page tables (4GiB+)
401 mov rcx, 0x0000000000000000
402 mov rax, 0x000000010000008F
403 mov rdi, 0x0000000000014000
404 buildem:
405 stosq
406 add rax, 0x0000000000200000
407 add rcx, 1
408 cmp rcx, 30720 ; Another 60 GiB (We already mapped 4 GiB)
409 jne buildem
410 ; We have 64 GiB mapped now
412 ; Build a temporary IDT
413 xor rdi, rdi ; create the 64-bit IDT (at linear address 0x0000000000000000)
415 mov rcx, 32
416 make_exception_gates: ; make gates for exception handlers
417 mov rax, exception_gate
418 push rax ; save the exception gate to the stack for later use
419 stosw ; store the low word (15..0) of the address
420 mov ax, SYS64_CODE_SEL
421 stosw ; store the segment selector
422 mov ax, 0x8E00
423 stosw ; store exception gate marker
424 pop rax ; get the exception gate back
425 shr rax, 16
426 stosw ; store the high word (31..16) of the address
427 shr rax, 16
428 stosd ; store the extra high dword (63..32) of the address.
429 xor rax, rax
430 stosd ; reserved
431 dec rcx
432 jnz make_exception_gates
434 mov rcx, 256-32
435 make_interrupt_gates: ; make gates for the other interrupts
436 mov rax, interrupt_gate
437 push rax ; save the interrupt gate to the stack for later use
438 stosw ; store the low word (15..0) of the address
439 mov ax, SYS64_CODE_SEL
440 stosw ; store the segment selector
441 mov ax, 0x8F00
442 stosw ; store interrupt gate marker
443 pop rax ; get the interrupt gate back
444 shr rax, 16
445 stosw ; store the high word (31..16) of the address
446 shr rax, 16
447 stosd ; store the extra high dword (63..32) of the address.
448 xor rax, rax
449 stosd ; reserved
450 dec rcx
451 jnz make_interrupt_gates
453 ; Set up the exception gates for all of the CPU exceptions
454 ; The following code will be seriously busted if the exception gates are moved above 16MB
455 mov word [0x00*16], exception_gate_00
456 mov word [0x01*16], exception_gate_01
457 mov word [0x02*16], exception_gate_02
458 mov word [0x03*16], exception_gate_03
459 mov word [0x04*16], exception_gate_04
460 mov word [0x05*16], exception_gate_05
461 mov word [0x06*16], exception_gate_06
462 mov word [0x07*16], exception_gate_07
463 mov word [0x08*16], exception_gate_08
464 mov word [0x09*16], exception_gate_09
465 mov word [0x0A*16], exception_gate_10
466 mov word [0x0B*16], exception_gate_11
467 mov word [0x0C*16], exception_gate_12
468 mov word [0x0D*16], exception_gate_13
469 mov word [0x0E*16], exception_gate_14
470 mov word [0x0F*16], exception_gate_15
471 mov word [0x10*16], exception_gate_16
472 mov word [0x11*16], exception_gate_17
473 mov word [0x12*16], exception_gate_18
474 mov word [0x13*16], exception_gate_19
476 mov rdi, 0x21 ; Set up Keyboard IRQ handler
477 mov rax, keyboard
478 call create_gate
479 mov rdi, 0x28 ; Set up RTC IRQ handler
480 mov rax, rtc
481 call create_gate
482 mov rdi, 0xF8 ; Set up Spurious handler
483 mov rax, spurious
484 call create_gate
486 lidt [IDTR64] ; load IDT register
488 ; Debug
489 mov al, '4'
490 mov [0x000B809E], al
491 ; mov al, '5'
492 ; call serial_send_64
494 ; Clear memory 0xf000 - 0xf7ff for the infomap (2048 bytes)
495 xor rax, rax
496 mov rcx, 256
497 mov rdi, 0x000000000000F000
498 clearmapnext:
499 stosq
500 dec rcx
501 cmp rcx, 0
502 jne clearmapnext
504 call init_acpi ; Find and process the ACPI tables
506 call init_cpu ; Setup CPU
508 call init_ioapic ; Setup the IO-APIC(s), also activate interrupts
510 ; Debug
511 mov al, '6' ; CPU Init complete
512 mov [0x000B809E], al
513 ; mov al, '6'
514 ; call serial_send_64
516 ; Make sure exceptions are working.
517 ; xor rax, rax
518 ; xor rbx, rbx
519 ; xor rcx, rcx
520 ; xor rdx, rdx
521 ; div rax
523 call hdd_setup ; Gather Hard Drive information
525 ; Debug
526 mov al, '8' ; HDD Init complete
527 mov [0x000B809E], al
528 ; mov al, '8'
529 ; call serial_send_64
531 ; Find init64.cfg
532 ; mov rbx, configname
533 ; call findfile
534 ; cmp rbx, 0
535 ; je near noconfig ; If the config file was not found we just use the default settings.
536 mov al, 1
537 mov byte [cfg_default], al ; We have a config file
539 ; Read in the first cluster of init64.cfg
540 ; mov rdi, 0x0000000000100000
541 ; call readcluster
543 ; Parse init64.cfg
544 ; Get Kernel name
545 ; get SMP setting
547 ; noconfig:
549 ; Init of SMP
550 call smp_setup
552 ; Reset the stack to the proper location (was set to 0x8000 previously)
553 mov rsi, [os_LocalAPICAddress] ; We would call os_smp_get_id here but the stack is not ...
554 add rsi, 0x20 ; ... yet defined. It is safer to find the value directly.
555 lodsd ; Load a 32-bit value. We only want the high 8 bits
556 shr rax, 24 ; Shift to the right and AL now holds the CPU's APIC ID
557 shl rax, 10 ; shift left 10 bits for a 1024byte stack
558 add rax, 0x0000000000050400 ; stacks decrement when you "push", start at 1024 bytes in
559 mov rsp, rax ; Pure64 leaves 0x50000-0x9FFFF free so we use that
561 ; Debug
562 mov al, '6' ; SMP Init complete
563 mov [0x000B809C], al
564 mov al, '0'
565 mov [0x000B809E], al
566 ; mov al, 'E'
567 ; call serial_send_64
569 ; Calculate amount of usable RAM from Memory Map
570 xor rcx, rcx
571 mov rsi, 0x0000000000004000 ; E820 Map location
572 readnextrecord:
573 lodsq
574 lodsq
575 lodsd
576 cmp eax, 0 ; Are we at the end?
577 je endmemcalc
578 cmp eax, 1 ; Usuable RAM
579 je goodmem
580 cmp eax, 3 ; ACPI Reclaimable
581 je goodmem
582 cmp eax, 6 ; BIOS Reclaimable
583 je goodmem
584 lodsd
585 lodsq
586 jmp readnextrecord
587 goodmem:
588 sub rsi, 12
589 lodsq
590 add rcx, rax
591 lodsq
592 lodsq
593 jmp readnextrecord
595 endmemcalc:
596 shr rcx, 20 ; Value is in bytes so do a quick divide by 1048576 to get MiB's
597 add cx, 1 ; The BIOS will usually report actual memory minus 1
598 and cx, 0xFFFE ; Make sure it is an even number (in case we added 1 to an even number)
599 mov word [mem_amount], cx
601 ; Debug
602 mov al, '2'
603 mov [0x000B809E], al
605 ; Convert CPU speed value to string
606 xor rax, rax
607 mov ax, [cpu_speed]
608 mov rdi, speedtempstring
609 call os_int_to_string
611 ; Convert CPU amount value to string
612 xor rax, rax
613 mov ax, [cpu_activated]
614 mov rdi, cpu_amount_string
615 call os_int_to_string
617 ; Convert RAM amount value to string
618 xor rax, rax
619 mov ax, [mem_amount]
620 mov rdi, memtempstring
621 call os_int_to_string
623 ; Build the infomap
624 xor rdi, rdi
625 mov di, 0x5000
626 mov rax, [os_ACPITableAddress]
627 stosq
628 mov eax, [os_BSP]
629 stosd
631 mov di, 0x5010
632 mov ax, [cpu_speed]
633 stosw
634 mov ax, [cpu_activated]
635 stosw
636 mov ax, [cpu_detected]
637 stosw
639 mov di, 0x5020
640 mov ax, [mem_amount]
641 stosw
643 mov di, 0x5030
644 mov al, [cfg_mbr]
645 stosb
646 mov al, [os_IOAPICCount]
647 stosb
649 mov di, 0x5040
650 mov eax, [VBEModeInfoBlock.PhysBasePtr]
651 stosd
652 mov ax, [VBEModeInfoBlock.XResolution]
653 stosw
654 mov ax, [VBEModeInfoBlock.YResolution]
655 stosw
657 mov di, 0x5060
658 mov rax, [os_LocalAPICAddress]
659 stosq
660 xor ecx, ecx
661 mov cl, [os_IOAPICCount]
662 mov rsi, os_IOAPICAddress
663 nextIOAPIC:
664 lodsq
665 stosq
666 sub cl, 1
667 cmp cl, 0
668 jne nextIOAPIC
670 ; Initialization is now complete... write a message to the screen
671 mov rsi, msg_done
672 call os_print_string
674 ; Write an extra message if we are using the default config
675 cmp byte [cfg_default], 1
676 je nodefaultconfig
677 mov al, 2
678 mov ah, 28
679 call os_move_cursor
680 mov rsi, msg_noconfig
681 call os_print_string
682 nodefaultconfig:
684 ; Debug
685 mov al, '4'
686 mov [0x000B809E], al
688 ; Print info on CPU, MEM, and HD
689 mov ax, 0x0004
690 call os_move_cursor
691 mov rsi, msg_CPU
692 call os_print_string
693 mov rsi, speedtempstring
694 call os_print_string
695 mov rsi, msg_mhz
696 call os_print_string
697 mov rsi, cpu_amount_string
698 call os_print_string
700 mov rsi, msg_MEM
701 call os_print_string
702 mov rsi, memtempstring
703 call os_print_string
704 mov rsi, msg_mb
705 call os_print_string
707 mov rsi, msg_HDD
708 call os_print_string
709 mov rsi, hdtempstring
710 call os_print_string
711 mov rsi, msg_mb
712 call os_print_string
714 ; =============================================================================
715 %ifdef PURE64_CHAIN_LOADING
716 mov rsi, 0x8000+7168 ; Memory offset to end of pure64.sys
717 mov rdi, 0x100000 ; Destination address at the 1MiB mark
718 mov rcx, 0x1000 ; For up to 32KiB kernel (4096 x 8)
719 rep movsq ; Copy 8 bytes at a time
720 jmp fini ; Print starting message and jump to kernel
721 %endif
722 ; =============================================================================
724 ; Print a message that the kernel is being loaded
725 mov ax, 0x0006
726 call os_move_cursor
727 mov rsi, msg_loadingkernel
728 call os_print_string
730 ; Find the kernel file
731 mov rsi, kernelname
732 call findfile
733 cmp ax, 0x0000
734 je near nokernel
736 ; Debug
737 push rax
738 mov al, '6'
739 mov [0x000B809E], al
740 pop rax
742 ; Load 64-bit kernel from drive to 0x0000000000010000
743 mov rdi, 0x0000000000100000
744 readfile_getdata:
745 push rax
746 mov al, '.' ; Show loading progress
747 call os_print_char
748 pop rax
749 call readcluster ; store in memory
750 cmp ax, 0xFFFF ; Value for end of cluster chain.
751 jne readfile_getdata ; Are there more clusters? If so then read again.. if not fall through.
753 ; Print a message that the kernel has been loaded
754 mov rsi, msg_done
755 call os_print_string
757 fini: ; For chainloading
759 ; Print a message that the kernel is being started
760 mov ax, 0x0008
761 call os_move_cursor
762 mov rsi, msg_startingkernel
763 call os_print_string
765 ; Debug
766 ; mov al, ' ' ; Clear the debug messages
767 ; mov [0x000B809A], al
768 ; mov [0x000B809C], al
769 ; mov [0x000B809E], al
771 ; mov al, '-'
772 ; call serial_send_64
774 ; Clear all registers (skip the stack pointer)
775 xor rax, rax ; aka r0
776 xor rbx, rbx ; aka r3
777 xor rcx, rcx ; aka r1
778 xor rdx, rdx ; aka r2
779 xor rsi, rsi ; aka r6
780 xor rdi, rdi ; aka r7
781 xor rbp, rbp ; aka r5
782 xor r8, r8
783 xor r9, r9
784 xor r10, r10
785 xor r11, r11
786 xor r12, r12
787 xor r13, r13
788 xor r14, r14
789 xor r15, r15
791 jmp 0x0000000000100000 ; Jump to the kernel
793 nokernel:
794 mov al, 6
795 mov ah, 0
796 call os_move_cursor
797 mov rsi, kernelerror
798 call os_print_string
799 nokernelhalt:
801 jmp nokernelhalt
803 ; 64-bit function to send a char our via serial
804 ;serial_send_64:
805 ; push rdx
806 ; push rax ; Save RAX since the serial line status check clobbers AL
807 ; mov dx, 0x03FD ; Serial Line Status register
808 ;serial_send_wait_64:
809 ; in al, dx
810 ; bt ax, 5 ; Copy bit 5 (THR is empty) to the Carry Flag
811 ; jnc serial_send_wait_64 ; If the bit is not set then the queue isn't ready for another byte
812 ; pop rax ; Get the byte back from the stack
813 ; mov dx, 0x03F8 ; Serial data register
814 ; out dx, al ; Send the byte
815 ; pop rdx
816 ; ret
818 %include "init_cpu.asm"
819 %include "init_acpi.asm"
820 %include "init_ioapic.asm"
821 %include "init_hdd.asm"
822 %include "init_smp.asm"
823 %include "syscalls.asm"
824 %include "interrupt.asm"
825 %include "pci.asm"
826 %include "fat16.asm"
827 %include "sysvar.asm"
829 ; Pad to an even KB file (6 KiB)
830 times 7168-($-$$) db 0x90
832 ; =============================================================================
833 ; EOF