1 ; =============================================================================
2 ; Pure64 -- a 64-bit OS loader written in Assembly for x86-64 systems
3 ; Copyright (C) 2008-2011 Return Infinity -- see LICENSE.TXT
6 ; =============================================================================
16 ; Get the BIOS E820 Memory Map
17 ; use the INT 0x15, eax= 0xE820 BIOS function to get a memory map
18 ; inputs: es:di -> destination buffer for 24 byte entries
19 ; outputs: bp = entry count, trashes all registers except esi
21 mov edi, 0x00004000 ; location that memory map will be stored to
22 xor ebx, ebx ; ebx must be 0 to start
23 xor bp, bp ; keep an entry count in bp
24 mov edx, 0x0534D4150 ; Place "SMAP" into edx
26 mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry
27 mov ecx, 24 ; ask for 24 bytes
29 jc nomemmap
; carry set on first call means "unsupported function"
30 mov edx, 0x0534D4150 ; Some BIOSes apparently trash this register?
31 cmp eax, edx ; on success, eax must have been reset to "SMAP"
33 test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless)
37 mov eax, 0xe820 ; eax, ecx get trashed on every int 0x15 call
38 mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry
39 mov ecx, 24 ; ask for 24 bytes again
41 jc memmapend
; carry set means "end of list already reached"
42 mov edx, 0x0534D4150 ; repair potentially trashed register
44 jcxz skipent
; skip any 0 length entries
45 cmp cl, 20 ; got a 24 byte ACPI 3.X response?
47 test byte [es:di + 20], 1 ; if so: is the "ignore this data" bit clear?
50 mov ecx, [es:di + 8] ; get lower dword of memory region length
51 test ecx, ecx ; is the qword == 0?
53 mov ecx, [es:di + 12] ; get upper dword of memory region length
54 jecxz skipent
; if length qword is 0, skip entry
56 inc bp ; got a good entry: ++count, move to next storage spot
59 test ebx, ebx ; if ebx resets to 0, list is complete
62 mov byte [cfg_e820
], 0 ; No memory map function
64 xor eax, eax ; Create a blank record for termination (32 bytes)
82 ; Configure serial port 1
84 mov al, 11100011b ; 9600 baud, no parity, 8 data bits, 1 stop bit
88 ; Set PIT Channel 0 to fire at 1000Hz (Divisor = 1193180 / hz)
89 mov al, 0x36 ; Set Timer
91 mov al, 0xA9 ; We want 100MHz so 0x2E9B
92 out 0x40, al ; 1000MHz would be 0x04A9
96 ; Set keyboard repeat rate to max
98 out 0x60, al ; Set Typematic Rate/Delay
100 out 0x60, al ; 30 cps and .25 second delay
102 out 0x60, al ; Set/Reset LEDs
104 out 0x60, al ; all off
110 or al, 00000010b ; Bit 2 (0) Data Mode to BCD, Bit 1 (1) 24 hour mode
118 cmp byte [cfg_vesa
], 1 ; Check if VESA should be enabled
119 jne VBEdone
; If not then skip VESA init
120 mov edi, VBEModeInfoBlock
; VBE data will be stored at this address
121 mov ax, 0x4F01 ; GET SuperVGA MODE INFORMATION - http://www.ctyme.com/intr/rb-0274.htm
122 ; 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
123 ; 0x4112 is 640x480x24bit 0x4129 is 640x480x32bit
124 ; 0x4115 is 800x600x24bit 0x412E is 800x600x32bit
125 ; 0x4118 is 1024x768x24bit 0x4138 is 1024x768x32bit
126 ; 0x411B is 1280x1024x24bit 0x413D is 1280x1024x32bit
127 mov cx, 0x4112 ; Put your desired mode here
128 mov bx, cx ; Mode is saved to BX for the set command later
131 cmp ax, 0x004F ; Return value in AX should equal 0x004F if supported and sucessful
133 cmp byte[VBEModeInfoBlock.BitsPerPixel
], 24 ; Make sure this matches the number of bits for the mode!
134 jne VBEfail
; If set bit mode was unsucessful then bail out
136 mov ax, 0x4F02 ; SET SuperVGA VIDEO MODE - http://www.ctyme.com/intr/rb-0275.htm
138 cmp ax, 0x004F ; Return value in AX should equal 0x004F if supported and sucessful
144 mov byte [cfg_vesa
], 0 ; Clear the VESA config as it was not sucessful
149 ; As heard on an episode of Jerry Springer.. "It's time to lose the zero (8259 PIC) and get with a hero (IOAPIC)".
150 ; http://osdever.net/tutorials/apicarticle.php
151 mov al, 00010001b ; begin PIC 1 initialization
153 mov al, 00010001b ; begin PIC 2 initialization
155 mov al, 0x20 ; IRQ 0-7: interrupts 20h-27h
157 mov al, 0x28 ; IRQ 8-15: interrupts 28h-2Fh
168 mov al, 11111110b ; Disable all IRQs except for timer
177 ; =============================================================================