:: limine / common / protos / limine_asm.asm_ia32 4.6 KB raw

1
%ifdef UEFI
2
extern _GLOBAL_OFFSET_TABLE_
3
%endif
4
5
section .data
6
7
local_gdt:
8
    dq 0
9
10
    dq 0x00209b0000000000
11
    dq 0x0000930000000000
12
  .top:
13
14
local_gdt_ptr:
15
    dw local_gdt.top - local_gdt - 1
16
    dd local_gdt
17
    dd 0
18
19
old_gdt_ptr:
20
    dw 0
21
    dq 0
22
23
old_cs:
24
    dq 0
25
26
interrupt_state:
27
    dd 0
28
29
old_ds:
30
    dq 0
31
old_es:
32
    dq 0
33
old_fs:
34
    dq 0
35
old_gs:
36
    dq 0
37
old_ss:
38
    dq 0
39
40
%ifdef UEFI
41
paging_state:
42
    dd 0
43
44
pae_state:
45
    dd 0
46
47
old_pagemap:
48
    dd 0
49
%endif
50
51
section .text
52
53
; void limine_memcpy_64_asm(int paging_mode, void *pagemap, uint64_t dst, uint64_t src, size_t count);
54
;
55
; Both endpoints are 64-bit-wide. Low-memory callers cast pointers
56
; through (uint64_t)(uintptr_t). Identity mapping makes low addresses
57
; valid as 64-bit virtual addresses inside the long-mode copy.
58
59
global limine_memcpy_64_asm
60
limine_memcpy_64_asm:
61
    push ebp
62
    mov ebp, esp
63
64
    pusha
65
66
%ifdef UEFI
67
    call .get_got
68
  .get_got:
69
    pop ebx
70
    add ebx, _GLOBAL_OFFSET_TABLE_ + $$ - .get_got wrt ..gotpc
71
%endif
72
73
    pushfd
74
    mov eax, dword [esp]
75
    add esp, 4
76
    and eax, 0x200
77
%ifdef UEFI
78
    mov dword [ebx + interrupt_state wrt ..gotoff], eax
79
%else
80
    mov dword [interrupt_state], eax
81
%endif
82
83
    cli
84
85
%ifdef UEFI
86
    ; Disable paging if needed and save old pagemap
87
    mov eax, cr0
88
    and eax, (1 << 31)
89
    mov dword [ebx + paging_state wrt ..gotoff], eax
90
    mov eax, cr0
91
    btr eax, 31
92
    mov cr0, eax
93
94
    mov eax, cr3
95
    mov dword [ebx + old_pagemap wrt ..gotoff], eax
96
%endif
97
98
    mov eax, [ebp+12] ; pagemap
99
    mov cr3, eax
100
101
    ; Enable CR4.LA57
102
    cmp dword [ebp+8], 0 ; paging_mode
103
    je .no_la57
104
    mov eax, cr4
105
    bts eax, 12
106
    mov cr4, eax
107
  .no_la57:
108
109
    ; Enable CR4.PAE
110
%ifdef UEFI
111
    mov eax, cr4
112
    and eax, (1 << 5)
113
    mov [ebx + pae_state wrt ..gotoff], eax
114
%endif
115
    mov eax, cr4
116
    bts eax, 5
117
    mov cr4, eax
118
119
    ; Enable EFER.LME
120
    mov ecx, 0xc0000080
121
    rdmsr
122
    bts eax, 8
123
    wrmsr
124
125
    ; Enable CR0.PG
126
    mov eax, cr0
127
    bts eax, 31
128
    mov cr0, eax
129
130
    ; Save old segments
131
%ifdef UEFI
132
    mov [ebx + old_ss wrt ..gotoff], ss
133
    mov [ebx + old_gs wrt ..gotoff], gs
134
    mov [ebx + old_fs wrt ..gotoff], fs
135
    mov [ebx + old_es wrt ..gotoff], es
136
    mov [ebx + old_ds wrt ..gotoff], ds
137
%else
138
    mov [old_ss], ss
139
    mov [old_gs], gs
140
    mov [old_fs], fs
141
    mov [old_es], es
142
    mov [old_ds], ds
143
%endif
144
145
    ; Save old CS
146
    mov eax, cs
147
%ifdef UEFI
148
    mov dword [ebx + old_cs wrt ..gotoff], eax
149
%else
150
    mov dword [old_cs], eax
151
%endif
152
153
    ; Save old GDT
154
%ifdef UEFI
155
    sgdt [ebx + old_gdt_ptr wrt ..gotoff]
156
%else
157
    sgdt [old_gdt_ptr]
158
%endif
159
160
    ; Load new GDT
161
%ifdef UEFI
162
    lgdt [ebx + local_gdt_ptr wrt ..gotoff]
163
%else
164
    lgdt [local_gdt_ptr]
165
%endif
166
167
    ; Go 64
168
    push 0x08
169
    call .p1
170
  .p1:
171
    add dword [esp], .mode64 - .p1
172
    retf
173
174
bits 64
175
  .mode64:
176
    mov eax, 0x10
177
    mov ds, eax
178
    mov es, eax
179
    mov fs, eax
180
    mov gs, eax
181
    mov ss, eax
182
183
    mov rdi, qword [rbp+16]
184
    mov rsi, qword [rbp+24]
185
    mov ecx, dword [rbp+32]
186
187
    rep movsb
188
189
    ; Restore old GDT
190
%ifdef UEFI
191
    lgdt [ebx + old_gdt_ptr wrt ..gotoff]
192
%else
193
    lgdt [abs old_gdt_ptr]
194
%endif
195
196
    ; Restore old segments
197
%ifdef UEFI
198
    mov ds, [ebx + old_ds wrt ..gotoff]
199
    mov es, [ebx + old_es wrt ..gotoff]
200
    mov fs, [ebx + old_fs wrt ..gotoff]
201
    mov gs, [ebx + old_gs wrt ..gotoff]
202
    mov ss, [ebx + old_ss wrt ..gotoff]
203
%else
204
    mov ds, [abs old_ds]
205
    mov es, [abs old_es]
206
    mov fs, [abs old_fs]
207
    mov gs, [abs old_gs]
208
    mov ss, [abs old_ss]
209
%endif
210
211
    ; Go 32
212
%ifdef UEFI
213
    push qword [ebx + old_cs wrt ..gotoff]
214
%else
215
    push qword [abs old_cs]
216
%endif
217
    call .p2
218
  .p2:
219
    add qword [rsp], .mode32 - .p2
220
    retfq
221
222
bits 32
223
  .mode32:
224
    ; Disable CR0.PG
225
    mov eax, cr0
226
    btr eax, 31
227
    mov cr0, eax
228
229
    ; Disable EFER.LME
230
    mov ecx, 0xc0000080
231
    rdmsr
232
    btr eax, 8
233
    wrmsr
234
235
    ; Disable CR4.PAE
236
%ifdef UEFI
237
    cmp dword [ebx + pae_state wrt ..gotoff], 0
238
    jne .no_disable_pae
239
%endif
240
    mov eax, cr4
241
    btr eax, 5
242
    mov cr4, eax
243
%ifdef UEFI
244
  .no_disable_pae:
245
%endif
246
247
    ; Disable CR4.LA57
248
    mov eax, cr4
249
    btr eax, 12
250
    mov cr4, eax
251
252
    ; Invalidate pagemap
253
    xor eax, eax
254
    mov cr3, eax
255
256
%ifdef UEFI
257
    mov eax, dword [ebx + old_pagemap wrt ..gotoff]
258
    mov cr3, eax
259
260
    cmp dword [ebx + paging_state wrt ..gotoff], 0
261
    je .no_paging
262
    mov eax, cr0
263
    bts eax, 31
264
    mov cr0, eax
265
  .no_paging:
266
%endif
267
268
%ifdef UEFI
269
    cmp dword [ebx + interrupt_state wrt ..gotoff], 0
270
%else
271
    cmp dword [interrupt_state], 0
272
%endif
273
    je .no_ints
274
    sti
275
  .no_ints:
276
277
    popa
278
    pop ebp
279
280
    ret
281
282
section .note.GNU-stack noalloc noexec nowrite progbits
tab: 248 wrap: offon