* remove "\r" nonsense
[mascara-docs.git] / amd64 / bareMetalOS-0.5.3 / os / kernel64.asm
blob175ca914a99b3bf64128657486dedf57f2860ccd
1 ; =============================================================================
2 ; BareMetal -- a 64-bit OS written in Assembly for x86-64 systems
3 ; Copyright (C) 2008-2012 Return Infinity -- see LICENSE.TXT
5 ; The BareMetal OS kernel. Assemble with NASM
6 ; =============================================================================
9 USE64
10 ORG 0x0000000000100000
12 %DEFINE BAREMETALOS_VER 'v0.5.2 (June 29, 2011)', 13, 'Copyright (C) 2008-2011 Return Infinity', 13, 0
13 %DEFINE BAREMETALOS_API_VER 1
15 kernel_start:
16 jmp start ; Skip over the function call index
17 nop
18 db 'BAREMETAL'
20 align 16 ; 0x0010
21 jmp os_print_string ; Jump to function
22 align 8
23 dq os_print_string ; Memory address of function
25 align 8 ; 0x0020
26 jmp os_print_char
27 align 8
28 dq os_print_char
30 align 8 ; 0x0030
31 jmp os_print_char_hex
32 align 8
33 dq os_print_char_hex
35 align 8 ; 0x0040
36 jmp os_print_newline
37 align 8
38 dq os_print_newline
40 align 8 ; 0x0050
41 jmp os_input_key_check
42 align 8
43 dq os_input_key_check
45 align 8 ; 0x0060
46 jmp os_input_key_wait
47 align 8
48 dq os_input_key_wait
50 align 8 ; 0x0070
51 jmp os_input_string
52 align 8
53 dq os_input_string
55 align 8 ; 0x0080
56 jmp os_delay
57 align 8
58 dq os_delay
60 align 8 ; 0x0090
61 jmp os_speaker_tone
62 align 8
63 dq os_speaker_tone
65 align 8 ; 0x00A0
66 jmp os_speaker_off
67 align 8
68 dq os_speaker_off
70 align 8 ; 0x00B0
71 jmp os_speaker_beep
72 align 8
73 dq os_speaker_beep
75 align 8 ; 0x00C0
76 jmp os_move_cursor
77 align 8
78 dq os_move_cursor
80 align 8 ; 0x00D0
81 jmp os_string_length
82 align 8
83 dq os_string_length
85 align 8 ; 0x00E0
86 jmp os_string_find_char
87 align 8
88 dq os_string_find_char
90 align 8 ; 0x00F0
91 jmp os_string_copy
92 align 8
93 dq os_string_copy
95 align 8 ; 0x0100
96 jmp os_string_truncate
97 align 8
98 dq os_string_truncate
100 align 8 ; 0x0110
101 jmp os_string_join
102 align 8
103 dq os_string_join
105 align 8 ; 0x0120
106 jmp os_string_chomp
107 align 8
108 dq os_string_chomp
110 align 8 ; 0x0130
111 jmp os_string_strip
112 align 8
113 dq os_string_strip
115 align 8 ; 0x0140
116 jmp os_string_compare
117 align 8
118 dq os_string_compare
120 align 8 ; 0x0150
121 jmp os_string_uppercase
122 align 8
123 dq os_string_uppercase
125 align 8 ; 0x0160
126 jmp os_string_lowercase
127 align 8
128 dq os_string_lowercase
130 align 8 ; 0x0170
131 jmp os_int_to_string
132 align 8
133 dq os_int_to_string
135 align 8 ; 0x0180
136 jmp os_string_to_int
137 align 8
138 dq os_string_to_int
140 align 8 ; 0x0190
141 jmp os_debug_dump_reg
142 align 8
143 dq os_debug_dump_reg
145 align 8 ; 0x01A0
146 jmp os_debug_dump_mem
147 align 8
148 dq os_debug_dump_mem
150 align 8 ; 0x01B0
151 jmp os_debug_dump_rax
152 align 8
153 dq os_debug_dump_rax
155 align 8 ; 0x01C0
156 jmp os_debug_dump_eax
157 align 8
158 dq os_debug_dump_eax
160 align 8 ; 0x01D0
161 jmp os_debug_dump_ax
162 align 8
163 dq os_debug_dump_ax
165 align 8 ; 0x01E0
166 jmp os_debug_dump_al
167 align 8
168 dq os_debug_dump_al
170 align 8 ; 0x01F0
171 jmp os_smp_reset
172 align 8
173 dq os_smp_reset
175 align 8 ; 0x0200
176 jmp os_smp_get_id
177 align 8
178 dq os_smp_get_id
180 align 8 ; 0x0210
181 jmp os_smp_enqueue
182 align 8
183 dq os_smp_enqueue
185 align 8 ; 0x0220
186 jmp os_smp_dequeue
187 align 8
188 dq os_smp_dequeue
190 align 8 ; 0x0230
191 jmp os_serial_send
192 align 8
193 dq os_serial_send
195 align 8 ; 0x0240
196 jmp os_serial_recv
197 align 8
198 dq os_serial_recv
200 align 8 ; 0x0250
201 jmp os_string_parse
202 align 8
203 dq os_string_parse
205 align 8 ; 0x0260
206 jmp os_get_argc
207 align 8
208 dq os_get_argc
210 align 8 ; 0x0270
211 jmp os_get_argv
212 align 8
213 dq os_get_argv
215 align 8 ; 0x0280
216 jmp os_smp_queuelen
217 align 8
218 dq os_smp_queuelen
220 align 8 ; 0x0290
221 jmp os_smp_wait
222 align 8
223 dq os_smp_wait
225 align 8 ; 0x02A0
226 jmp os_get_timecounter
227 align 8
228 dq os_get_timecounter
230 align 8 ; 0x02B0
231 jmp os_string_append
232 align 8
233 dq os_string_append
235 align 8 ; 0x02C0
236 jmp os_int_to_hex_string
237 align 8
238 dq os_int_to_hex_string
240 align 8 ; 0x02D0
241 jmp os_hex_string_to_int
242 align 8
243 dq os_hex_string_to_int
245 align 8 ; 0x02E0
246 jmp os_string_change_char
247 align 8
248 dq os_string_change_char
250 align 8 ; 0x02F0
251 jmp os_is_digit
252 align 8
253 dq os_is_digit
255 align 8 ; 0x0300
256 jmp os_is_alpha
257 align 8
258 dq os_is_alpha
260 align 8 ; 0x0310
261 jmp os_file_read
262 align 8
263 dq os_file_read
265 align 8 ; 0x0320
266 jmp os_file_write
267 align 8
268 dq os_file_write
270 align 8 ; 0x0330
271 jmp os_file_delete
272 align 8
273 dq os_file_delete
275 align 8 ; 0x0340
276 jmp os_file_get_list
277 align 8
278 dq os_file_get_list
280 align 8 ; 0x0350
281 jmp os_smp_run
282 align 8
283 dq os_smp_run
285 align 8 ; 0x0360
286 jmp os_smp_lock
287 align 8
288 dq os_smp_lock
290 align 8 ; 0x0370
291 jmp os_smp_unlock
292 align 8
293 dq os_smp_unlock
295 align 8 ; 0x0380
296 jmp os_print_string_with_color
297 align 8
298 dq os_print_string_with_color
300 align 8 ; 0x0390
301 jmp os_print_char_with_color
302 align 8
303 dq os_print_char_with_color
305 align 8 ; 0x03A0
306 jmp os_ethernet_tx
307 align 8
308 dq os_ethernet_tx
310 align 8 ; 0x03B0
311 jmp os_ethernet_rx
312 align 8
313 dq os_ethernet_rx
315 align 8 ; 0x03C0
316 jmp os_mem_allocate
317 align 8
318 dq os_mem_allocate
320 align 8 ; 0x03D0
321 jmp os_mem_release
322 align 8
323 dq os_mem_release
325 align 8 ; 0x03E0
326 jmp os_mem_get_free
327 align 8
328 dq os_mem_get_free
330 align 8 ; 0x03F0
331 jmp os_smp_numcores
332 align 8
333 dq os_smp_numcores
335 align 8 ; 0x0400
336 jmp os_file_get_size
337 align 8
338 dq os_file_get_size
340 align 8 ; 0x0410
341 jmp os_ethernet_avail
342 align 8
343 dq os_ethernet_avail
345 align 8 ; 0x0420
346 jmp os_print_char_hex_with_color
347 align 8
348 dq os_print_char_hex_with_color
350 align 8 ; 0x0430
351 jmp os_ethernet_tx_raw
352 align 8
353 dq os_ethernet_tx_raw
355 align 8 ; 0x0440
356 jmp os_screen_clear
357 align 8
358 dq os_screen_clear
360 align 8 ; 0x0450
361 jmp os_show_cursor
362 align 8
363 dq os_show_cursor
365 align 8 ; 0x0460
366 jmp os_hide_cursor
367 align 8
368 dq os_hide_cursor
370 align 8 ; 0x0470
371 jmp os_show_statusbar
372 align 8
373 dq os_show_statusbar
375 align 8 ; 0x0480
376 jmp os_hide_statusbar
377 align 8
378 dq os_hide_statusbar
380 align 8 ; 0x0490
381 jmp os_screen_update
382 align 8
383 dq os_screen_update
385 align 8 ; 0x04A0
386 jmp os_print_chars
387 align 8
388 dq os_print_chars
390 align 8 ; 0x04B0
391 jmp os_print_chars_with_color
392 align 8
393 dq os_print_chars_with_color
395 align 16
397 start:
399 call init_64 ; After this point we are in a working 64-bit enviroment
401 call init_pci
403 call init_net ; Initialize the network
405 call hdd_setup ; Gather information about the harddrive and set it up
407 call os_screen_clear ; Clear screen and display cursor
409 cmp byte [os_NetEnabled], 1 ; Print network details (if a supported NIC was initialized)
410 jne start_no_network
411 mov ax, 0x0013
412 call os_move_cursor
413 mov rsi, networkmsg
414 call os_print_string
415 call os_debug_dump_MAC
416 start_no_network:
418 mov ax, 0x0016 ; Print the "ready" message
419 call os_move_cursor
420 mov rsi, readymsg
421 call os_print_string
423 mov ax, 0x0018 ; Set the hardware cursor to the bottom left-hand corner
424 call os_move_cursor
425 call os_show_cursor
427 mov rsi, startupapp ; Look for a file called startup.app
428 mov rdi, programlocation ; We load the program to this location in memory (currently 0x00200000 : at the 2MB mark)
429 call os_file_read ; Read the file into memory
430 jc ap_clear ; If carry is set then the file was not found
432 xchg bx, bx
433 mov rax, programlocation ; 0x00200000 : at the 2MB mark
434 xor rbx, rbx ; No arguements required (The app can get them with os_get_argc and os_get_argv)
435 call os_smp_enqueue ; Queue the application to run on the next available core
437 ; Fall through to ap_clear as align fills the space with No-Ops
438 ; At this point the BSP is just like one of the AP's
441 align 16
443 ap_clear: ; All cores start here on first startup and after an exception
445 cli ; Disable interrupts on this core
447 ; Get local ID of the core
448 mov rsi, [os_LocalAPICAddress]
449 xor eax, eax ; Clear Task Priority (bits 7:4) and Task Priority Sub-Class (bits 3:0)
450 mov dword [rsi+0x80], eax ; APIC Task Priority Register (TPR)
451 mov eax, dword [rsi+0x20] ; APIC ID
452 shr rax, 24 ; Shift to the right and AL now holds the CPU's APIC ID
454 ; Calculate offset into CPU status table
455 mov rdi, cpustatus
456 add rdi, rax ; RDI points to this cores status byte (we will clear it later)
458 ; Set up the stack
459 shl rax, 21 ; Shift left 21 bits for a 2 MiB stack
460 add rax, [os_StackBase] ; The stack decrements when you "push", start at 2 MiB in
461 mov rsp, rax
463 ; Set the CPU status to "Present" and "Ready"
464 mov al, 00000001b ; Bit 0 set for "Present", Bit 1 clear for "Ready"
465 stosb ; Set status to Ready for this CPU
467 sti ; Re-enable interrupts on this core
469 ; Clear registers. Gives us a clean slate to work with
470 xor rax, rax ; aka r0
471 xor rcx, rcx ; aka r1
472 xor rdx, rdx ; aka r2
473 xor rbx, rbx ; aka r3
474 xor rbp, rbp ; aka r5, We skip RSP (aka r4) as it was previously set
475 xor rsi, rsi ; aka r6
476 xor rdi, rdi ; aka r7
477 xor r8, r8
478 xor r9, r9
479 xor r10, r10
480 xor r11, r11
481 xor r12, r12
482 xor r13, r13
483 xor r14, r14
484 xor r15, r15
486 ap_spin: ; Spin until there is a workload in the queue
487 cmp word [os_QueueLen], 0 ; Check the length of the queue
488 je ap_halt ; If the queue was empty then jump to the HLT
489 call os_smp_dequeue ; Try to pull a workload out of the queue
490 jnc ap_process ; Carry clear if successful, jump to ap_process
492 ap_halt: ; Halt until a wakup call is received
493 hlt ; If carry was set we fall through to the HLT
494 jmp ap_spin ; Try again
496 ap_process: ; Set the status byte to "Busy" and run the code
498 push rsi
499 push rax
500 mov rsi, [os_LocalAPICAddress]
501 xor eax, eax
502 mov al, 0x10
503 mov dword [rsi+0x80], eax ; APIC Task Priority Register (TPR)
504 pop rax
505 pop rsi
508 push rdi ; Push RDI since it is used temporarily
509 push rax ; Push RAX since os_smp_get_id uses it
510 mov rdi, cpustatus
511 call os_smp_get_id ; Set RAX to the APIC ID
512 add rdi, rax
513 mov al, 00000011b ; Bit 0 set for "Present", Bit 1 set for "Busy"
514 stosb
515 pop rax ; Pop RAX (holds the workload code address)
516 pop rdi ; Pop RDI (holds the variable/variable address)
518 mov r15, rax
520 call os_get_argc
521 mov rcx, rax
522 cmp al, 1
523 je noargs
525 mov rdi, os_args
526 sub rcx, 1
527 shl rcx, 3
528 add rdi, rcx
529 shr rcx, 3
530 add rcx, 1
531 nextargv:
532 sub al, 1
533 call os_get_argv
534 mov [rdi], rsi
535 sub rdi, 8
536 cmp al, 1
537 jne nextargv
539 noargs:
540 mov al, 0
541 call os_get_argv
542 mov [os_args], rsi
543 mov rsi, os_args ; ARGV[0]
545 mov rdi, rcx ; ARGC
546 mov rax, r15
548 call rax ; Run the code
550 jmp ap_clear ; Reset the stack, clear the registers, and wait for something else to work on
553 ; Includes
554 %include "init_64.asm"
555 %include "init_pci.asm"
556 %include "init_net.asm"
557 %include "init_hdd.asm"
558 %include "syscalls.asm"
559 %include "drivers.asm"
560 %include "interrupt.asm"
561 %include "cli.asm"
562 %include "ipv4.asm"
563 %include "sysvar.asm" ; Include this last to keep the read/write variables away from the code
565 ;times 16384-($-$$) db 0 ; Set the compiled kernel binary to at least this size in bytes
567 ; =============================================================================
568 ; EOF