initial commit
[newsys] / bootefi / src / bootefi.asm
1         bits 64
2         org 1000h
3
4 %include "src/serial.inc"
5
6 BOOT_SERVICES           equ 96
7 BOOT_GET_MEMORY_MAP     equ 56
8 BOOT_EXIT_BOOT_SERVICES equ 232
9
10 start:
11         mov [efihandle], rcx
12         mov [systab], rdx
13
14         ; retrieve memory map
15         ; args: RCX, RDX, R8, and R9.
16         lea rcx, [mmap_size]
17         lea rdx, [mmapbuf]
18         lea r8, [mmap_key]
19         lea r9, [mmap_descsz]
20         lea rax, [mmap_descver]
21         push rax
22         sub rsp, 32
23         mov rax, [systab]
24         mov rbx, [rax + BOOT_SERVICES]
25         call [rbx + BOOT_GET_MEMORY_MAP]
26         add rsp, 40
27         ; exit boot services
28         mov rcx, [efihandle]
29         mov rdx, [mmap_key]
30         mov rax, [systab]
31         mov rbx, [rax + BOOT_SERVICES]
32         call [rbx + BOOT_EXIT_BOOT_SERVICES]
33
34         ; move code to absolute 1000h
35         call get_rip
36 .after_call:
37         sub rax, .after_call - start
38         mov rsi, rax    ; source address
39         mov rdi, start  ; destination
40         mov rcx, end - start
41         shr rcx, 2      ; dwords
42         cld
43         rep movsd       ; copy code to make it absolute
44
45         mov rax, .abs
46         jmp rax
47 .abs:
48         call setup_serial
49
50         ; switch to 32-bit compatibility long mode
51         lgdt [gdtlim]
52         push word 8
53         push qword start32
54         retfq
55
56 get_rip:
57         mov rax, [rsp]
58         ret
59
60         ; serial port setup
61 setup_serial:
62         ; set clock divisor
63         mov al, LCTL_DLAB
64         mov dx, UART_LCTL
65         out dx, al
66         mov ax, DIV_9600
67         mov dx, UART_DIVLO
68         out dx, al
69         mov al, ah
70         mov dx, UART_DIVHI
71         out dx, al
72         ; set format 8n1
73         mov al, LCTL_8N1
74         mov dx, UART_LCTL
75         out dx, al
76         ; clear and enable fifo
77         mov al, FIFO_ENABLE_CLEAR
78         mov dx, UART_FIFO
79         out dx, al
80         ; assert RTS and DTR
81         mov al, MCTL_DTR_RTS_OUT2
82         mov dx, UART_MCTL
83         out dx, al
84         ret
85
86
87 ; ----------- 32bit code ----------
88
89         bits 32
90 start32:
91         mov ax, 10h
92         mov ds, ax
93         mov ss, ax
94         mov es, ax
95         mov gs, ax
96         mov fs, ax
97
98         ; disable paging to deactivate long mode
99         mov eax, cr0
100         and eax, 7fffffffh
101         mov cr0, eax
102
103         ; disable long mode (EFER.LME = 0)
104         ; TODO: EFER is MSR c0000080, LME is bit 8
105         mov ecx, 0c0000080h
106         rdmsr
107         and eax, 0fffffeffh
108         wrmsr
109
110         ; halt for ever
111         sti
112 halt:   hlt
113         jmp halt
114
115 ser_putchar:
116         mov ah, al
117         ; wait until transmit register is empty
118         mov dx, UART_LSTAT
119 .wait:  in al, dx
120         and al, LST_TREG_EMPTY
121         jz .wait
122         mov dx, UART_DATA
123         mov al, ah
124         out dx, al
125         ret
126
127 ser_putstr:
128         mov al, [si]
129         test al, al
130         jz .done
131         call ser_putchar
132         inc si
133         jmp ser_putstr
134 .done:  ret
135
136
137 ; ---------- data ------------
138
139         align 8
140 efihandle dq 0
141 systab dq 0
142 ; memory map data
143 mmap_size dq 4096
144 mmap_key dq 0
145 mmap_descsz dq 0
146 mmap_descver dq 0
147
148         align 4096
149 mmapbuf: times 4096 db 0
150
151 str_hello db 'hello!',13,10,0
152
153         align 4
154 gdtlim  dw 31
155 gdtbase dq gdt
156
157         align 8
158 gdt:    ; 0: null segment
159         dd 0, 0
160         ; 1: code - base:0, lim:4g, G:4k, 32bit, avl, pres|app, dpl:0, type:code/non-conf/rd
161         dd 0x0000ffff
162         dd 0x00cf9a00
163         ; 2: data - base:0, lim:4g, G:4k, 32bit, avl, pres|app, dpl:0, type:data/rw
164         dd 0x0000ffff
165         dd 0x00cf9200
166         ; 3: code16
167         dd 0x0000ffff
168         dd 0x00009a00
169
170         align 4
171 end:
172 ; vi:ft=nasm: