1 ; =============================================================================
2 ; BareMetal -- a 64-bit OS written in Assembly for x86-64 systems
3 ; Copyright (C) 2008-2012 Return Infinity -- see LICENSE.TXT
6 ; =============================================================================
14 ; Make sure that memory range 0x110000 - 0x200000 is cleared
15 mov rdi
, os_SystemVariables
21 cmp rcx
, 122880 ; Clear 960 KiB
24 mov ax, 0x000A ; Set the cursor to 0,10 (needs to happen before anything is printed to the screen)
27 xor rdi
, rdi
; create the 64-bit IDT (at linear address 0x0000000000000000) as defined by Pure64
29 ; Create exception gate stubs (Pure64 has already set the correct gate markers)
31 mov rax
, exception_gate
32 make_exception_gate_stubs:
36 jnz make_exception_gate_stubs
38 ; Create interrupt gate stubs (Pure64 has already set the correct gate markers)
40 mov rax
, interrupt_gate
41 make_interrupt_gate_stubs:
45 jnz make_interrupt_gate_stubs
47 ; Set up the exception gates for all of the CPU exceptions
50 mov rax
, exception_gate_00
54 add rax
, 16 ; The exception gates are aligned at 16 bytes
56 jnz make_exception_gates
58 ; Set up the IRQ handlers (Network IRQ handler is configured in init_net)
73 ; Rate defines how often the RTC interrupt is triggered
74 ; Rate is a 4-bit value from 1 to 15. 1 = 32768Hz, 6 = 1024Hz, 15 = 2Hz
75 ; RTC value must stay at 32.768KHz or the computer will not keep the correct time
76 ; http://wiki.osdev.org/RTC
78 mov al, 0x0A ; Status Register A
81 test al, 0x80 ; Is there an update in process?
82 jne rtc_poll
; If so then keep polling
83 mov al, 0x0A ; Status Register A
85 mov al, 00101101b ; RTC@32.768KHz (0010), Rate@8Hz (1101)
87 mov al, 0x0C ; Acknowledge the RTC
105 mov dx, 0x03C8 ; DAC Address Write Mode Register
107 mov dx, 0x03C9 ; DAC Data Register
108 mov rbx
, 16 ; 16 lines
110 mov rcx
, 16 ; 16 colors
124 jne nextline
; Set the next 16 colors to the same
125 mov eax, 0x14 ; Fix for color 6
126 mov dx, 0x03c8 ; DAC Address Write Mode Register
128 mov dx, 0x03c9 ; DAC Data Register
141 ; Grab data from Pure64's infomap
143 lodsd ; Load the BSP ID
144 mov ebx, eax ; Save it to EBX
146 lodsw ; Load the number of activated cores
147 mov cx, ax ; Save it to CX
150 mov [os_LocalAPICAddress
], rax
152 mov [os_IOAPICAddress
], rax
156 mov [os_NumCores
], ax
160 mov [os_MemAmount
], ax ; In MiB's
162 ; Build the OS memory table
165 ; Initialize all AP's to run our reset code. Skip the BSP
167 mov rsi
, 0x0000000000005100 ; Location in memory of the Pure64 CPU data
171 lodsb ; Load the CPU APIC ID
174 call os_smp_reset
; Reset the CPU
181 ; Enable specific interrupts
182 mov rcx
, 1 ; Enable Keyboard
184 call ioapic_entry_write
185 mov rcx
, 8 ; Enable RTC
186 mov rax
, 0x0100000000000928 ; Lowest priority
187 ; mov rax, 0x28 ; Handled by APIC ID 0 (BSP)
188 call ioapic_entry_write
190 call os_seed_random
; Seed the RNG
195 ; rax = address of handler
196 ; rdi = gate # to configure
201 shl rdi
, 4 ; quickly multiply rdi by 16
202 stosw ; store the low word (15..0)
204 add rdi
, 4 ; skip the gate marker
205 stosw ; store the high word (31..16)
207 stosd ; store the high dword (63..32)
214 init_memory_map: ; Build the OS memory table
219 ; Build a fresh memory map for the system
220 mov rdi
, os_MemoryMap
223 mov cx, [os_MemAmount
]
224 shr cx, 1 ; Divide actual memory by 2
229 stosb ; Mark the first 2 MiB as in use (by Kernel and system buffers)
230 stosb ; As well as the second 2 MiB (by loaded application)
231 ; The CLI should take care of the Application memory
233 ; Allocate memory for CPU stacks (2 MiB's for each core)
235 mov cx, [os_NumCores
] ; Get the amount of cores in the system
236 call os_mem_allocate
; Allocate a page for each core
237 cmp rcx
, 0 ; os_mem_allocate returns 0 on failure
240 mov [os_StackBase
], rax
; Store the Stack base address
251 mov rsi
, memory_message
253 call os_print_string_with_color
256 jmp system_failure_hang
259 ; -----------------------------------------------------------------------------
260 ; ioapic_reg_write -- Write to an I/O APIC register
261 ; IN: EAX = Value to write
262 ; ECX = Index of register
263 ; OUT: Nothing. All registers preserved
266 mov rsi
, [os_IOAPICAddress
]
267 mov dword [rsi
], ecx ; Write index to register selector
268 mov dword [rsi
+ 0x10], eax ; Write data to window register
271 ; -----------------------------------------------------------------------------
274 ; -----------------------------------------------------------------------------
275 ; ioapic_entry_write -- Write to an I/O APIC entry in the redirection table
276 ; IN: RAX = Data to write to entry
277 ; ECX = Index of the entry
278 ; OUT: Nothing. All registers preserved
283 ; Calculate index for lower DWORD
284 shl rcx
, 1 ; Quick multiply by 2
285 add rcx
, 0x10 ; IO Redirection tables start at 0x10
288 call ioapic_reg_write
293 call ioapic_reg_write
298 ; -----------------------------------------------------------------------------
301 ; =============================================================================