Commit 7b6d5b4e authored by Ian Seyler's avatar Ian Seyler

Initial commit

parents
*DS_Store
*.sys
This diff is collapsed.
; =============================================================================
; Pure64 Multiboot -- a 64-bit OS/software loader written in Assembly for x86-64 systems
; Copyright (C) 2008-2017 Return Infinity -- see LICENSE.TXT
;
; http://stackoverflow.com/questions/33488194/creating-a-simple-multiboot-kernel-loaded-with-grub2
; https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#OS-image-format
; =============================================================================
[BITS 32]
[global _start]
[ORG 0x100000] ;If using '-f bin' we need to specify the
;origin point for our code with ORG directive
;multiboot loaders load us at physical
;address 0x100000
FLAG_ALIGN equ 1<<0 ; align loaded modules on page boundaries
FLAG_MEMINFO equ 1<<1 ; provide memory map
FLAG_VIDEO equ 1<<2 ; set video mode
FLAG_AOUT_KLUDGE equ 1<<16
;FLAGS[16] indicates to GRUB we are not
;an ELF executable and the fields
;header address, load address, load end address;
;bss end address and entry address will be available
;in Multiboot header
MAGIC equ 0x1BADB002
;magic number GRUB searches for in the first 8k
;of the kernel file GRUB is told to load
FLAGS equ FLAG_ALIGN | FLAG_MEMINFO | FLAG_VIDEO | FLAG_AOUT_KLUDGE
CHECKSUM equ -(MAGIC + FLAGS)
mode_type equ 0 ; Linear
width equ 1024
height equ 768
depth equ 24
_start: ; We need some code before the multiboot header
xor eax, eax ; Clear eax and ebx in the event
xor ebx, ebx ; we are not loaded by GRUB.
jmp multiboot_entry ; Jump over the multiboot header
align 4 ; Multiboot header must be 32-bit aligned
multiboot_header:
dd MAGIC ; magic
dd FLAGS ; flags
dd CHECKSUM ; checksum
dd multiboot_header ; header address
dd _start ; load address of code entry point
dd 0x00 ; load end address : not necessary
dd 0x00 ; bss end address : not necessary
dd multiboot_entry ; entry address GRUB will start at
dd mode_type
dd width
dd height
dd depth
align 16
multiboot_entry:
push 0
popf
cld ; Clear direction flag
; Copy memory map
mov esi, ebx ; GRUB stores the Multiboot info table at the address in EBX
mov edi, 0x6000 ; We want the memory map stored here
add esi, 44 ; Memory map address at this offset in the Mutliboot table
lodsd ; Grab the memory map size in bytes
mov ecx, eax
lodsd ; Grab the memory map address
mov esi, eax
memmap_entry:
lodsd ; Size of entry
cmp eax, 0
je memmap_end
movsd ; base_addr_low
movsd ; base_addr_high
movsd ; length_low
movsd ; length_high
movsd ; type
xor eax, eax
stosd ; padding
stosd
stosd
jmp memmap_entry
memmap_end:
xor eax, eax
mov ecx, 8
rep stosd
; Copy loader and kernel to expected location
mov esi, multiboot_end
mov edi, 0x00008000
mov ecx, 8192 ; Copy 32K
rep movsd ; Copy loader to expected address
cli
jmp 0x00008000
times 512-$+$$ db 0 ; Padding
multiboot_end:
; =============================================================================
; EOF
; =============================================================================
; Pure64 Multiboot 2 -- a 64-bit OS/software loader written in Assembly for x86-64 systems
; Copyright (C) 2008-2017 Return Infinity -- see LICENSE.TXT
;
; http://nongnu.askapache.com/grub/phcoder/multiboot.pdf
; =============================================================================
[BITS 32]
[global _start]
[ORG 0x100000] ;If using '-f bin' we need to specify the
;origin point for our code with ORG directive
;multiboot loaders load us at physical
;address 0x100000
MAGIC equ 0xE85250D6
ARCHITECHTURE equ 0
HEADER_LENGTH equ multiboot_header_end - multiboot_header_start
CHECKSUM equ 0x100000000 - (MAGIC + ARCHITECHTURE + HEADER_LENGTH)
_start: ; We need some code before the multiboot header
xor eax, eax ; Clear eax and ebx in the event
xor ebx, ebx ; we are not loaded by GRUB.
jmp multiboot_entry ; Jump over the multiboot header
align 8 ; Multiboot 2 header must be 64-bit aligned
multiboot_header_start:
dd MAGIC
dd ARCHITECHTURE
dd HEADER_LENGTH
dd CHECKSUM
entry_address_tag_start:
dw 3
dw 0
dd entry_address_tag_end - entry_address_tag_start
dq multiboot_entry
entry_address_tag_end:
framebuffer_tag_start:
dw 5
dw 0
dd framebuffer_tag_end - framebuffer_tag_start
dd 800
dd 600
dd 32
framebuffer_tag_end:
dw 0 ; End type
dw 0
dd 8
multiboot_header_end:
multiboot_entry:
cmp eax, 0x36D76289 ; Magic value
jne error
error:
jmp $
; =============================================================================
; Pure64 PXE Start -- a 64-bit OS/software loader written in Assembly for x86-64 systems
; Copyright (C) 2008-2018 Return Infinity -- see LICENSE.TXT
;
; This is a stub file for loading Pure64 and a kernel/software package via PXE.
;
; Windows - copy /b pxestart.bin + pure64.sys + kernel64.sys pxeboot.bin
; Unix - cat pxestart.bin pure64.sys kernel64.sys > pxeboot.bin
;
; Max size of the resulting pxeboot.bin is 33792 bytes. 1K for the PXE loader
; stub and up to 32KiB for the code/data. PXE loads the file to address
; 0x00007C00 (Just like a boot sector).
;
; File Sizes
; pxestart.bin 1024 bytes
; pure64.sys 4096 bytes
; kernel64.sys 16384 bytes (or so)
; =============================================================================
USE16
org 0x7C00
start:
cli ; Disable interrupts
cld ; Clear direction flag
xor eax, eax
mov ss, ax
mov es, ax
mov ds, ax
mov sp, 0x7C00
sti ; Enable interrupts
; Get the BIOS E820 Memory Map
; use the INT 0x15, eax= 0xE820 BIOS function to get a memory map
; inputs: es:di -> destination buffer for 24 byte entries
; outputs: bp = entry count, trashes all registers except esi
do_e820:
mov edi, 0x00006000 ; location that memory map will be stored to
xor ebx, ebx ; ebx must be 0 to start
xor bp, bp ; keep an entry count in bp
mov edx, 0x0534D4150 ; Place "SMAP" into edx
mov eax, 0xe820
mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry
mov ecx, 24 ; ask for 24 bytes
int 0x15
jc nomemmap ; carry set on first call means "unsupported function"
mov edx, 0x0534D4150 ; Some BIOSes apparently trash this register?
cmp eax, edx ; on success, eax must have been reset to "SMAP"
jne nomemmap
test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless)
je nomemmap
jmp jmpin
e820lp:
mov eax, 0xe820 ; eax, ecx get trashed on every int 0x15 call
mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry
mov ecx, 24 ; ask for 24 bytes again
int 0x15
jc memmapend ; carry set means "end of list already reached"
mov edx, 0x0534D4150 ; repair potentially trashed register
jmpin:
jcxz skipent ; skip any 0 length entries
cmp cl, 20 ; got a 24 byte ACPI 3.X response?
jbe notext
test byte [es:di + 20], 1 ; if so: is the "ignore this data" bit clear?
je skipent
notext:
mov ecx, [es:di + 8] ; get lower dword of memory region length
test ecx, ecx ; is the qword == 0?
jne goodent
mov ecx, [es:di + 12] ; get upper dword of memory region length
jecxz skipent ; if length qword is 0, skip entry
goodent:
inc bp ; got a good entry: ++count, move to next storage spot
add di, 32
skipent:
test ebx, ebx ; if ebx resets to 0, list is complete
jne e820lp
nomemmap:
; mov byte [cfg_e820], 0 ; No memory map function
memmapend:
xor eax, eax ; Create a blank record for termination (32 bytes)
mov ecx, 8
rep stosd
; Enable the A20 gate
set_A20:
in al, 0x64
test al, 0x02
jnz set_A20
mov al, 0xD1
out 0x64, al
check_A20:
in al, 0x64
test al, 0x02
jnz check_A20
mov al, 0xDF
out 0x60, al
mov si, msg_Load ; Print message
call print_string_16
mov edi, VBEModeInfoBlock ; VBE data will be stored at this address
mov ax, 0x4F01 ; GET SuperVGA MODE INFORMATION - http://www.ctyme.com/intr/rb-0274.htm
; CX queries the mode, it should be in the form 0x41XX as bit 14 is set for LFB and bit 8 is set for VESA mode
; 0x4112 is 640x480x24bit, 0x4129 should be 32bit
; 0x4115 is 800x600x24bit, 0x412E should be 32bit
; 0x4118 is 1024x768x24bit, 0x4138 should be 32bit
; 0x411B is 1280x1024x24bit, 0x413D should be 32bit
mov cx, 0x4118 ; Put your desired mode here
mov bx, cx ; Mode is saved to BX for the set command later
int 0x10
cmp ax, 0x004F ; Return value in AX should equal 0x004F if command supported and successful
jne halt
cmp byte [VBEModeInfoBlock.BitsPerPixel], 24 ; Make sure this matches the number of bits for the mode!
jne halt ; If set bit mode was unsuccessful then bail out
or bx, 0x4000 ; Use linear/flat frame buffer model (set bit 14)
mov ax, 0x4F02 ; SET SuperVGA VIDEO MODE - http://www.ctyme.com/intr/rb-0275.htm
int 0x10
cmp ax, 0x004F ; Return value in AX should equal 0x004F if supported and successful
jne halt
mov ax, [0x8006]
cmp ax, 0x3436 ; Match against the Pure64 binary
jne magic_fail
; At this point we are done with real mode and BIOS interrupts. Jump to 32-bit mode.
cli ; No more interrupts
lgdt [cs:GDTR32] ; Load GDT register
mov eax, cr0
or al, 0x01 ; Set protected mode bit
mov cr0, eax
jmp 8:0x8000 ; Jump to 32-bit protected mode
magic_fail:
mov si, msg_MagicFail
call print_string_16
halt:
hlt
jmp halt
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; 16-bit Function to print a string to the screen
; input: SI - Address of start of string
print_string_16: ; Output string in SI to screen
pusha
mov ah, 0x0E ; int 0x10 teletype function
.repeat:
lodsb ; Get char from string
test al, al
jz .done ; If char is zero, end of string
int 0x10 ; Otherwise, print it
jmp short .repeat
.done:
popa
ret
;------------------------------------------------------------------------------
align 16
GDTR32: ; Global Descriptors Table Register
dw gdt32_end - gdt32 - 1 ; limit of GDT (size minus one)
dq gdt32 ; linear address of GDT
align 16
gdt32:
dw 0x0000, 0x0000, 0x0000, 0x0000 ; Null desciptor
dw 0xFFFF, 0x0000, 0x9A00, 0x00CF ; 32-bit code descriptor
dw 0xFFFF, 0x0000, 0x9200, 0x00CF ; 32-bit data descriptor
gdt32_end:
msg_Load db "Pure64 PXE v1.0", 0
msg_MagicFail db " - Error!", 0
times 510-$+$$ db 0 ; Pad out for a normal boot sector
sign dw 0xAA55 ; BIOS boot sector signature
times 1024-$+$$ db 0 ; Padding so that Pure64 will be aligned at 0x8000
VBEModeInfoBlock: equ 0x5C00
; VESA
; Mandatory information for all VBE revisions
VBEModeInfoBlock.ModeAttributes equ VBEModeInfoBlock + 0 ; DW - mode attributes
VBEModeInfoBlock.WinAAttributes equ VBEModeInfoBlock + 2 ; DB - window A attributes
VBEModeInfoBlock.WinBAttributes equ VBEModeInfoBlock + 3 ; DB - window B attributes
VBEModeInfoBlock.WinGranularity equ VBEModeInfoBlock + 4 ; DW - window granularity in KB
VBEModeInfoBlock.WinSize equ VBEModeInfoBlock + 6 ; DW - window size in KB
VBEModeInfoBlock.WinASegment equ VBEModeInfoBlock + 8 ; DW - window A start segment
VBEModeInfoBlock.WinBSegment equ VBEModeInfoBlock + 10 ; DW - window B start segment
VBEModeInfoBlock.WinFuncPtr equ VBEModeInfoBlock + 12 ; DD - real mode pointer to window function
VBEModeInfoBlock.BytesPerScanLine equ VBEModeInfoBlock + 16 ; DW - bytes per scan line
; Mandatory information for VBE 1.2 and above
VBEModeInfoBlock.XResolution equ VBEModeInfoBlock + 18 ; DW - horizontal resolution in pixels or characters
VBEModeInfoBlock.YResolution equ VBEModeInfoBlock + 20 ; DW - vertical resolution in pixels or characters
VBEModeInfoBlock.XCharSize equ VBEModeInfoBlock + 22 ; DB - character cell width in pixels
VBEModeInfoBlock.YCharSize equ VBEModeInfoBlock + 23 ; DB - character cell height in pixels
VBEModeInfoBlock.NumberOfPlanes equ VBEModeInfoBlock + 24 ; DB - number of memory planes
VBEModeInfoBlock.BitsPerPixel equ VBEModeInfoBlock + 25 ; DB - bits per pixel
VBEModeInfoBlock.NumberOfBanks equ VBEModeInfoBlock + 26 ; DB - number of banks
VBEModeInfoBlock.MemoryModel equ VBEModeInfoBlock + 27 ; DB - memory model type
VBEModeInfoBlock.BankSize equ VBEModeInfoBlock + 28 ; DB - bank size in KB
VBEModeInfoBlock.NumberOfImagePages equ VBEModeInfoBlock + 29 ; DB - number of image pages
VBEModeInfoBlock.Reserved equ VBEModeInfoBlock + 30 ; DB - reserved (0x00 for VBE 1.0-2.0, 0x01 for VBE 3.0)
; Direct Color fields (required for direct/6 and YUV/7 memory models)
VBEModeInfoBlock.RedMaskSize equ VBEModeInfoBlock + 31 ; DB - size of direct color red mask in bits
VBEModeInfoBlock.RedFieldPosition equ VBEModeInfoBlock + 32 ; DB - bit position of lsb of red mask
VBEModeInfoBlock.GreenMaskSize equ VBEModeInfoBlock + 33 ; DB - size of direct color green mask in bits
VBEModeInfoBlock.GreenFieldPosition equ VBEModeInfoBlock + 34 ; DB - bit position of lsb of green mask
VBEModeInfoBlock.BlueMaskSize equ VBEModeInfoBlock + 35 ; DB - size of direct color blue mask in bits
VBEModeInfoBlock.BlueFieldPosition equ VBEModeInfoBlock + 36 ; DB - bit position of lsb of blue mask
VBEModeInfoBlock.RsvdMaskSize equ VBEModeInfoBlock + 37 ; DB - size of direct color reserved mask in bits
VBEModeInfoBlock.RsvdFieldPosition equ VBEModeInfoBlock + 38 ; DB - bit position of lsb of reserved mask
VBEModeInfoBlock.DirectColorModeInfo equ VBEModeInfoBlock + 39 ; DB - direct color mode attributes
; Mandatory information for VBE 2.0 and above
VBEModeInfoBlock.PhysBasePtr equ VBEModeInfoBlock + 40 ; DD - physical address for flat memory frame buffer
VBEModeInfoBlock.Reserved1 equ VBEModeInfoBlock + 44 ; DD - Reserved - always set to 0
VBEModeInfoBlock.Reserved2 equ VBEModeInfoBlock + 48 ; DD - Reserved - always set to 0
; EOF
#!/bin/bash
nasm pure64.asm -o pure64.sys
cd bootsectors
nasm mbr.asm -o ../mbr.sys
nasm pxestart.asm -o ../pxestart.sys
nasm multiboot.asm -o ../multiboot.sys
nasm multiboot2.asm -o ../multiboot2.sys
cd ..
#!/bin/sh
rm -f *.sys
; =============================================================================
; Pure64 -- a 64-bit OS/software loader written in Assembly for x86-64 systems
; Copyright (C) 2008-2017 Return Infinity -- see LICENSE.TXT
;
; INIT ACPI
; =============================================================================
init_acpi:
mov rsi, 0x00000000000E0000 ; Start looking for the Root System Description Pointer Structure
mov rbx, 'RSD PTR ' ; This in the Signature for the ACPI Structure Table (0x2052545020445352)
searchingforACPI:
lodsq ; Load a quad word from RSI and store in RAX, then increment RSI by 8
cmp rax, rbx
je foundACPI
cmp rsi, 0x00000000000FFFFF ; Keep looking until we get here
jge noACPI ; ACPI tables couldn't be found, Fail.
jmp searchingforACPI
foundACPI: ; Found a Pointer Structure, verify the checksum
push rsi
xor ebx, ebx
mov ecx, 20 ; As per the spec only the first 20 bytes matter
sub rsi, 8 ; Bytes 0 thru 19 must sum to zero
nextchecksum:
lodsb ; Get a byte
add bl, al ; Add it to the running total
sub cl, 1
cmp cl, 0
jne nextchecksum
pop rsi
cmp bl, 0
jne searchingforACPI ; Checksum didn't check out? Then keep looking.
lodsb ; Checksum
lodsd ; OEMID (First 4 bytes)
lodsw ; OEMID (Last 2 bytes)
lodsb ; Grab the Revision value (0 is v1.0, 1 is v2.0, 2 is v3.0, etc)
cmp al, 0
je foundACPIv1 ; If AL is 0 then the system is using ACPI v1.0
jmp foundACPIv2 ; Otherwise it is v2.0 or higher
foundACPIv1:
xor eax, eax
lodsd ; Grab the 32 bit physical address of the RSDT (Offset 16).
mov rsi, rax ; RSI now points to the RSDT
lodsd ; Grab the Signiture
cmp eax, 'RSDT' ; Make sure the signiture is valid
jne novalidacpi ; Not the same? Bail out
sub rsi, 4
mov [os_ACPITableAddress], rsi ; Save the RSDT Table Address
add rsi, 4
xor eax, eax
lodsd ; Length
add rsi, 28 ; Skip to the Entry offset
sub eax, 36 ; EAX holds the table size. Subtract the preamble
shr eax, 2 ; Divide by 4
mov rdx, rax ; RDX is the entry count
xor ecx, ecx
foundACPIv1_nextentry:
lodsd
push rax
add ecx, 1
cmp ecx, edx
je findACPITables
jmp foundACPIv1_nextentry
foundACPIv2:
lodsd ; RSDT Address
lodsd ; Length
lodsq ; Grab the 64 bit physical address of the XSDT (Offset 24).
mov rsi, rax ; RSI now points to the XSDT
lodsd ; Grab the Signiture
cmp eax, 'XSDT' ; Make sure the signiture is valid
jne novalidacpi ; Not the same? Bail out
sub rsi, 4
mov [os_ACPITableAddress], rsi ; Save the XSDT Table Address
add rsi, 4
xor eax, eax
lodsd ; Length
add rsi, 28 ; Skip to the start of the Entries (offset 36)
sub eax, 36 ; EAX holds the table size. Subtract the preamble
shr eax, 3 ; Divide by 8
mov rdx, rax ; RDX is the entry count
xor ecx, ecx
foundACPIv2_nextentry:
lodsq
push rax
add ecx, 1
cmp ecx, edx
jne foundACPIv2_nextentry
findACPITables:
xor ecx, ecx
nextACPITable:
pop rsi
lodsd
add ecx, 1
mov ebx, 'APIC' ; Signature for the Multiple APIC Description Table
cmp eax, ebx
je foundAPICTable
mov ebx, 'HPET' ; Signiture for the HPET Description Table
cmp eax, ebx
je foundHPETTable
cmp ecx, edx
jne nextACPITable
jmp init_smp_acpi_done ;noACPIAPIC
foundAPICTable:
call parseAPICTable
jmp nextACPITable
foundHPETTable:
call parseHPETTable
jmp nextACPITable
init_smp_acpi_done:
ret
noACPI:
novalidacpi:
jmp $
; -----------------------------------------------------------------------------
parseAPICTable:
push rcx
push rdx
lodsd ; Length of MADT in bytes
mov ecx, eax ; Store the length in ECX
xor ebx, ebx ; EBX is the counter
lodsb ; Revision
lodsb ; Checksum
lodsd ; OEMID (First 4 bytes)
lodsw ; OEMID (Last 2 bytes)
lodsq ; OEM Table ID
lodsd ; OEM Revision
lodsd ; Creator ID
lodsd ; Creator Revision
xor eax, eax
lodsd ; Local APIC Address
mov [os_LocalAPICAddress], rax ; Save the Address of the Local APIC
lodsd ; Flags
add ebx, 44
mov rdi, 0x0000000000005100 ; Valid CPU IDs
readAPICstructures:
cmp ebx, ecx
jge parseAPICTable_done
lodsb ; APIC Structure Type
cmp al, 0x00 ; Processor Local APIC
je APICapic
cmp al, 0x01 ; I/O APIC
je APICioapic
cmp al, 0x02 ; Interrupt Source Override
je APICinterruptsourceoverride
; cmp al, 0x03 ; Non-maskable Interrupt Source (NMI)
; je APICnmi
; cmp al, 0x04 ; Local APIC NMI
; je APIClocalapicnmi
; cmp al, 0x05 ; Local APIC Address Override
; je APICaddressoverride
cmp al, 0x09 ; Processor Local x2APIC
je APICx2apic
; cmp al, 0x0A ; Local x2APIC NMI
; je APICx2nmi
jmp APICignore
APICapic:
xor eax, eax
xor edx, edx
lodsb ; Length (will be set to 8)
add ebx, eax
lodsb ; ACPI Processor ID
lodsb ; APIC ID
xchg eax, edx ; Save the APIC ID to EDX
lodsd ; Flags (Bit 0 set if enabled/usable)
bt eax, 0 ; Test to see if usable
jnc readAPICstructures ; Read the next structure if CPU not usable
inc word [cpu_detected]
xchg eax, edx ; Restore the APIC ID back to EAX
stosb
jmp readAPICstructures ; Read the next structure
APICioapic:
xor eax, eax
lodsb ; Length (will be set to 12)
add ebx, eax
lodsb ; IO APIC ID
lodsb ; Reserved
xor eax, eax
lodsd ; IO APIC Address
push rdi
push rcx
mov rdi, os_IOAPICAddress
xor ecx, ecx
mov cl, [os_IOAPICCount]
shl cx, 3 ; Quick multiply by 8
add rdi, rcx
pop rcx
stosd ; Store the IO APIC Address
lodsd ; System Vector Base
stosd ; Store the IO APIC Vector Base
pop rdi
inc byte [os_IOAPICCount]
jmp readAPICstructures ; Read the next structure
APICinterruptsourceoverride:
xor eax, eax
lodsb ; Length (will be set to 10)
add ebx, eax
lodsb ; Bus
lodsb ; Source
lodsd ; Global System Interrupt
lodsw ; Flags
jmp readAPICstructures ; Read the next structure
APICx2apic:
xor eax, eax
xor edx, edx
lodsb ; Length (will be set to 16)
add ebx, eax
lodsw ; Reserved; Must be Zero
lodsd
xchg eax, edx ; Save the x2APIC ID to EDX
lodsd ; Flags (Bit 0 set if enabled/usable)
bt eax, 0 ; Test to see if usable
jnc APICx2apicEnd ; Read the next structure if CPU not usable
xchg eax, edx ; Restore the x2APIC ID back to EAX
; TODO - Save the ID's somewhere
APICx2apicEnd:
lodsd ; ACPI Processor UID
jmp readAPICstructures ; Read the next structure
APICignore:
xor eax, eax
lodsb ; We have a type that we ignore, read the next byte
add ebx, eax
add rsi, rax
sub rsi, 2 ; For the two bytes just read
jmp readAPICstructures ; Read the next structure
parseAPICTable_done:
pop rdx
pop rcx
ret
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
parseHPETTable:
lodsd ; Length of HPET in bytes
lodsb ; Revision
lodsb ; Checksum
lodsd ; OEMID (First 4 bytes)
lodsw ; OEMID (Last 2 bytes)
lodsq ; OEM Table ID
lodsd ; OEM Revision
lodsd ; Creator ID
lodsd ; Creator Revision
lodsd ; Event Timer Block ID
lodsd ; Base Address Settings
lodsq ; Base Address Value
mov [os_HPETAddress], rax ; Save the Address of the HPET
lodsb ; HPET Number
lodsw ; Main Counter Minimum
lodsw ; Page Protection And OEM Attribute
ret
; -----------------------------------------------------------------------------
; =============================================================================
; EOF
; =============================================================================
; Pure64 -- a 64-bit OS/software loader written in Assembly for x86-64 systems
; Copyright (C) 2008-2017 Return Infinity -- see LICENSE.TXT
;
; INIT CPU - This code is called by all activated CPU cores in the system
; =============================================================================
init_cpu:
; Disable Cache
mov rax, cr0
btr rax, 29 ; Clear No Write Thru (Bit 29)
bts rax, 30 ; Set Cache Disable (Bit 30)
mov cr0, rax
; Flush Cache
wbinvd
; Disable Paging Global Extensions
mov rax, cr4
btr rax, 7 ; Clear Paging Global Extensions (Bit 7)
mov cr4, rax
mov rax, cr3
mov cr3, rax
; Disable MTRRs and Configure default memory type to UC
mov ecx, 0x000002FF
rdmsr
and eax, 0xFFFFF300 ; Clear MTRR Enable (Bit 11), Fixed Range MTRR Enable (Bit 10), and Default Memory Type (Bits 7:0) to UC (0x00)
wrmsr
; Setup variable-size address ranges
; Cache 0-64 MiB as type 6 (WB) cache
; See example in Intel Volume 3A. Example Base and Mask Calculations
; mov ecx, 0x00000200 ; MTRR_Phys_Base_MSR(0)
; mov edx, 0x00000000 ; Base is EDX:EAX, 0x0000000000000006
; mov eax, 0x00000006 ; Type 6 (write-back cache)
; wrmsr
; mov ecx, 0x00000201 ; MTRR_Phys_Mask_MSR(0)
;; mov edx, 0x00000000 ; Mask is EDX:EAX, 0x0000000001000800 (Because bochs sucks)
;; mov eax, 0x01000800 ; Bit 11 set for Valid
; mov edx, 0x0000000F ; Mask is EDX:EAX, 0x0000000F80000800 (2 GiB)
; mov eax, 0x80000800 ; Bit 11 set for Valid
; wrmsr
; MTRR notes:
; Base 0x0000000000000000 = 0 MiB
; Base 0x0000000080000000 = 2048 MiB, 2048 is 0x800
; Base 0x0000000100000000 = 4096 MiB, 4096 is 0x1000
; Mask 0x0000000F80000000 = 2048 MiB, 0xFFFFFFFFF - F80000000 = 7FFFFFFF = 2147483647 (~2 GiB)
; Mask 0x0000000FC0000000 = 1024 MiB, 0xFFFFFFFFF - FC0000000 = 3FFFFFFF = 1073741823 (~1 GiB)
; Mask 0x0000000FFC000000 = 64 MiB, 0xFFFFFFFFF - FFC000000 = 3FFFFFF = 67108863 (~64 MiB)
; Enable MTRRs
mov ecx, 0x000002FF
rdmsr
bts eax, 11 ; Set MTRR Enable (Bit 11), Only enables Variable Range MTRR's
wrmsr
; Flush Cache
wbinvd
; Enable Cache
mov rax, cr0
btr rax, 29 ; Clear No Write Thru (Bit 29)
btr rax, 30 ; Clear CD (Bit 30)
mov cr0, rax
; Enable Paging Global Extensions
; mov rax, cr4
; bts rax, 7 ; Set Paging Global Extensions (Bit 7)
; mov cr4, rax
; Enable Floating Point